设备端SDK(Android)文档

更新时间:2019-06-23 17:00:59

功能描述

摄像头直播: 支持RTMP推流,当前视频支持H264,音频支持G711a以及AAC_LC格式.
存储卡录像查看: 将存储在SD卡等外存中的录像文件推到服务端,支持seek到指定位置操作.
语音对讲: 与App端建立双向语音通道,设备端采集录音并实时发送至App端,同时接收到App端发送的语音进行播放.
拍照: 抓拍当前摄像头画面并上传至云端.
上报事件:上报带图片的事件给云端。

使用说明

SDK依赖引入

build.gradle中引入对SDK依赖

android {
    repositories {
        flatDir { dirs 'libs' }
    }
}

// 2. 将linkvisualipc的aar包手动拷贝到项目的libs目录下

// 3. 添加对linkvisualipc aar包以及linkkit的引用
implementation(name: 'linkvisualipc-1.2.0', ext: 'aar') // 具体版本请以拿到的SDK包为准
implementation 'com.aliyun.alink.linksdk:iot-linkkit:1.5.0'
linkvisualipc SDK使用JNI,so库支持: armeabi-v7a .

SDK初始化

请在Linkkit初始化完毕后对IPC SDK的初始化,需要传入设备三元组.

LinkKit.getInstance().init(this, params, new ILinkKitConnectListener() {
            @Override
            public void onError(AError error) {
                Log.d(TAG,
                    "onError() called with: error = [" + (error == null ? "null" : (error.getCode() + error.getMsg()))
                        + "]");

            }

            @Override
            public void onInitDone(Object data) {
                Log.d(TAG, "onInitDone() called with: data = [" + JSON.toJSONString(data) + "]");
                // 初始化IPC SDK
                IPCDev.getInstance().init(productKey, deviceName, deviceSecret);
            }

SDK消息监听

注册监听

IPC SDK需借助Linkkit的能力来完成消息监听和处理。注册监听需要两步,首先在原飞燕的同步异步服务调用监听器里加入对应的代码:

//注册飞燕监听异步服务调用监听器
LinkKit.getInstance().getDeviceThing().setServiceHandler(service.getIdentifier(),
                itResRequestHandler);
//飞燕的异步服务调用监听器
private ITResRequestHandler itResRequestHandler = new ITResRequestHandler() {
        @Override
        public void onProcess(String identify, Object result, ITResResponseCallback
            itResResponseCallback) {
            Log.d(TAG,
                "ITResRequestHandler  onProcess() called with: identify = [" + identify + "], result = ["
                    + JSON.toJSONString(result) + "], itResResponseCallback = ["
                    + itResResponseCallback + "]");
            /**
             * 添加IPC SDK的监听
             */
            IPCDev.getInstance().notifyAsyncTopicReceived(identify, result, itResResponseCallback);
        }

        @Override
        public void onSuccess(Object o, OutputParams outputParams) {
            Log.d(TAG,
                "onSuccess() called with: o = [" + JSON.toJSONString(o) + "], outputParams = [" + JSON
                    .toJSONString(outputParams) + "]");
        }

        @Override
        public void onFail(Object o, ErrorInfo errorInfo) {
            Log.d(TAG, "onFail() called with: o = [" + JSON.toJSONString(o) + "], errorInfo = [" + JSON
                .toJSONString(errorInfo) + "]");
        }
    };
/**
 * 注册飞燕同步服务调用的监听器
 */
LinkKit.getInstance().registerOnPushListener(connectNotifyListener);
//飞燕同步服务调用监听器
private IConnectNotifyListener connectNotifyListener = new IConnectNotifyListener() {
        @Override
        public void onNotify(String connectId, String topic, AMessage aMessage) {
            /**
             * 添加IPC SDK的监听
             */
            IPCDev.getInstance().notifySyncTopicReceived(connectId, topic, aMessage);

            if (CONNECT_ID.equals(connectId) && !TextUtils.isEmpty(topic) &&
                topic.startsWith("/sys/" + productKey + "/" + deviceName + "/rrpc/request")) {
                Log.d(TAG, "IConnectNotifyListener   onNotify() called with: connectId = [" + connectId + "], topic = ["
                    + topic + "], aMessage = ["
                    + new String((byte[])aMessage.data) + "]");
            }
        }

        @Override
        public boolean shouldHandle(String connectId, String topic) {
            return true;
        }

        @Override
        public void onConnectStateChange(String connectId, ConnectState connectState) {

        }
    };

SDK流处理

直播推流

整个处理流程分为以下几步:

  1. 注册直播事件监听器和流错误监听器
  2. IPC SDK收到服务端下发的开始推流指令后,会通过事先注册的直播流事件监听器(OnLiveStreamListener)来通知何时开始/结束推流/强制I帧.
  3. 推流中发生的错误也将通过流错误监听器(OnStreamErrorListener)来通知. 注意回调接口中不要执行阻塞任务。
// 设置直播流事件监听
IPCDev.getInstance().getIpcStreamManager().setOnLiveStreamListener(MainActivity.this);
// 设置流错误监听
IPCDev.getInstance().getIpcStreamManager().setOnStreamErrorListener(MainActivity.this);
public interface OnLiveStreamListener {
    /**
     * 收到开始推直播流请求
     *
     * @param streamId   流ID
     * @param streamType 码流类型: 0为主码流, 1为辅码流
     * @param preTimeInS 预先录制时间,单位S
     */
    void onStartPushLiveStreaming(final int streamId, final int streamType, final int preTimeInS);

    /**
     * 收到停止推流请求
     *
     * @param streamId 流ID
     */
    void onStopPushStreaming(final int streamId);

    /**
     * 收到强制I帧请求
     * 需立即构造一个I帧并发送
     * @param streamId 流ID
     */
    void onForceIFrame(int streamId);
}
public interface OnStreamErrorListener {
    /**
     * 流异常时回调
     * @param streamId
     * @param error 参考StreamError定义
     */
    void onError(int streamId, StreamError error);
}

流错误列表:

错误码 错误描述
StreamError.ERROR_STREAM_CREATE_FAILED 创建流实例失败
StreamError.ERROR_STREAM_START_FAILED 开流失败
StreamError.ERROR_STREAM_STOP_FAILED 停止流失败
StreamError.ERROR_STREAM_SEND_VIDEO_FAILED 发送视频数据失败
StreamError.ERROR_STREAM_SEND_AUDIO_FAILED 发送音频数据失败
StreamError.ERROR_STREAM_INVALID_PARAMS 无效的流参数
  1. 处理开始直播推流请求
  2. 当服务端下发推流请求时,回调OnLiveStreamListener.onStartPushLiveStreaming(int streamId, int streamType, int preTimeInS)方法来通知设备端需要开始采流并推流.
  3. 一般需要开启摄像头和录音机进行采流,对摄像头采集的数据调用MediaCodec进行H264编码,对录音机采集的数据进行G711a编码,提前设置对应格式的音视频参数,分别调用发送音视频的接口来持续发送采集到编码后的数据.
@Override
    public void onStartPushLiveStreaming(int streamId, int streamType, int preTimeInS) {
        this.streamId = streamId;
        try {

            // 构造视频参数
            VideoStreamParams videoStreamParams = new VideoStreamParams();
            // 直播流该参数始终为0
            videoStreamParams.setDurationInS(0); 
            videoStreamParams.setVideoFormat(VideoStreamParams.VIDEO_FORMAT_H264);

            // 构造音频参数
            AudioStreamParams audioStreamParams = new AudioStreamParams();
            audioStreamParams.setAudioChannel(AudioStreamParams.AUDIO_CHANNEL_MONO);
            audioStreamParams.setAudioFormat(AudioStreamParams.AUDIO_FORMAT_G711A);
            audioStreamParams.setAudioEncoding(AudioStreamParams.AUDIO_ENCODING_16BIT);
            audioStreamParams.setAudioSampleRate(AudioStreamParams.AUDIO_SAMPLE_RATE_8000);

            // 设置推流参数
            IPCDev.getInstance().getIpcStreamManager().setStreamParams(streamId, videoStreamParams, audioStreamParams);

            // TODO 开始采流、编码并发送音视频数据            
        } catch (NoSuchStreamException e) {
            e.printStackTrace();
        }
    }

发送音视频数据接口(IPCStreamManager):

/**
     * 发送音频帧数据
     *
     * @param streamId      流ID
     * @param data          源数据
     * @param offset        偏移量
     * @param length        数据长度
     * @param timeStampInMs 音频帧时间戳,单位ms
     */
    void sendAudioData(int streamId, byte[] data, int offset, int length, long timeStampInMs) throws NoSuchStreamException

     /**
     * 发送视频帧数据
     *
     * @param streamId      流ID
     * @param data          源数据
     * @param offset        偏移量
     * @param length        数据长度
     * @param isIFrame      是否为I帧(I帧数据需要包含SPS+PPS帧)
     * @param timeStampInMs 视频帧时间戳,单位ms
     */
    public void sendVideoData(int streamId, byte[] data, int offset, int length, boolean isIFrame, long timeStampInMs) throws NoSuchStreamException
  1. 处理结束推流请求
  2. 当服务端下发停止推流请求时,回调OnLiveStreamListener.onStopPushLiveStreaming()方法来通知设备端停止推流.
  3. 一般需要停止摄像头数据和录音机数据的采集,并调用IPCStreamManager的stopStreaming(int streamId)方法.
/**
     * 收到停止推流请求
     *
     * @param streamId 流ID
     */
    @Override
    public void onStopPushStreaming(int streamId) {
        // TODO 停止音视频数据的发送
        try {
            // 调用停止推流接口
            IPCDev.getInstance().getIpcStreamManager().stopStreaming(streamId);
        } catch (NoSuchStreamException e) {
            e.printStackTrace();
        }
    }
  1. 处理流错误
  2. 推流过程中需要处理流错误,通过OnStreamErrorListener.onError(int streamId, StreamError error)来接收和处理.

点播推流

整个处理流程分为以下几步:

  1. 注册点播事件监听器和流错误监听器
  2. IPC SDK收到服务端下发的开始推流指令后,会通过事先注册的点播流事件监听器(OnVodStreamListener)来通知何时开始/结束推流/暂停/恢复/seek等.
  3. 推流中发生的错误也将通过流错误监听器(OnStreamErrorListener)来通知. 注意回调接口中不要执行阻塞任务。
  4. 处理查询设备端录像列表请求
  5. App端发起查询设备端录像列表的请求,设备端会收到同步服务调用(rrpc/request),收到查询设备录像列表请求(详见物模型定义),响应该请求将当查询范围内的文件列表返回给App端.
@Override
        public void onNotify(String connectId, String topic, AMessage aMessage) {
            Log.d(TAG, "onNotify() called with: connectId = [" + connectId + "], topic = [" + topic + "], aMessage = ["
                    + new String((byte[]) aMessage.data) + "]");
            /**
             * 添加SDK的监听。
             */
            IPCDev.getInstance().notifySyncTopicReceived(connectId, topic, aMessage);

            // 处理同步服务调用
            if (CONNECT_ID.equals(connectId) && !TextUtils.isEmpty(topic) &&
                    topic.contains("rrpc")) {
                Log.d(TAG, "IConnectNotifyListener   onNotify() called with: connectId = [" + connectId + "], topic = ["
                        + topic + "], aMessage = ["
                        + new String((byte[]) aMessage.data) + "]");

                int code = 200;
                String data = "{}";

                JSONObject json = JSON.parseObject(new String((byte[]) aMessage.data));
                if (json != null) {
                    String method = json.getString("method");
                    JSONObject params = json.getJSONObject("params");
                    switch (method) {
                        // 查询设备录像列表请求
                        case "thing.service.QueryRecordList":
                            int beginTime = params.getIntValue("BeginTime");
                            int endTime = params.getIntValue("EndTime");
                            int querySize = params.getIntValue("QuerySize");
                            int type = params.getIntValue("Type");
                            appendLog("收到查询设备录像列表的请求: beginTime=" + beginTime +
                                    "\tendTime=" + endTime + "\tquerySize=" + querySize + "\ttype=" + type);

                            JSONArray resultArray = new JSONArray();
                            JSONObject item1 = new JSONObject();
                            item1.put("FileName", Base64.encode("file1".getBytes(), Base64.DEFAULT));
                            item1.put("BeginTime", System.currentTimeMillis() / 1000 - 200);
                            item1.put("EndTime", System.currentTimeMillis() / 1000 - 100);
                            item1.put("Size", 1024000);
                            item1.put("Type", 0);
                            resultArray.add(item1);

                            JSONObject item2 = new JSONObject();
                            item2.put("FileName", Base64.encode("file2".getBytes(), Base64.DEFAULT));
                            item2.put("BeginTime", System.currentTimeMillis() / 1000 - 100);
                            item2.put("EndTime", System.currentTimeMillis() / 1000);
                            item2.put("Size", 1024000);
                            item2.put("Type", 0);
                            resultArray.add(item2);

                            JSONObject result = new JSONObject();
                            result.put("RecordList", resultArray);

                            code = 200;
                            data = result.toJSONString();
                            break;
                        default:
                            break;
                    }
                }

                MqttPublishRequest request = new MqttPublishRequest();
                request.isRPC = false;
                request.topic = topic.replace("request", "response");
                String resId = topic.substring(topic.indexOf("rrpc/request/") + 13);
                request.msgId = resId;
                request.payloadObj = "{\"id\":\"" + resId + "\", \"code\":" + code + ",\"data\":" + data + "}";
                LinkKit.getInstance().publish(request, new IConnectSendListener() {
                    @Override
                    public void onResponse(ARequest aRequest, AResponse aResponse) {
                        appendLog("上报成功");
                    }

                    @Override
                    public void onFailure(ARequest aRequest, AError aError) {
                        appendLog("上报失败:" + aError.toString());
                    }
                });
            }
        }
  1. 处理开始开始推流指令
  2. App端请求上一步返回的列表中某个设备录像文件后,服务端会下发推流指令,回调OnVodStreamListener.onStartPushVodStreaming(int streamId, String fileName)方法来通知设备端需要将指定fileName的音频数据推流.

请注意: 文件名需使用Base64进行编码.

@Override
    public void onStartPushVodStreaming(int streamId, String fileName) {
        appendLog("开始推点播流 " + streamId + " 文件名:" + new String(Base64.decode(fileName, Base64.NO_WRAP)));

        try {
            // 构造视频参数
            VideoStreamParams videoStreamParams = new VideoStreamParams();
            // 该视频文件的时长,单位S
            videoStreamParams.setDurationInS(H264_DURATION_IN_S);
            videoStreamParams.setVideoFormat(VideoStreamParams.VIDEO_FORMAT_H264);

            // 构造音频参数
            AudioStreamParams audioStreamParams = new AudioStreamParams();
            audioStreamParams.setAudioChannel(AudioStreamParams.AUDIO_CHANNEL_MONO);
            audioStreamParams.setAudioFormat(AudioStreamParams.AUDIO_FORMAT_G711A);
            audioStreamParams.setAudioEncoding(AudioStreamParams.AUDIO_ENCODING_16BIT);
            audioStreamParams.setAudioSampleRate(AudioStreamParams.AUDIO_SAMPLE_RATE_8000);

            // 设置推流参数
            IPCDev.getInstance().getIpcStreamManager().setStreamParams(streamId, videoStreamParams, audioStreamParams);

            // TODO 读取fileName文件,调用发送音视频数据接口进行推流

        } catch (NoSuchStreamException e) {
            e.printStackTrace();
        }
    }
  1. 处理暂停/恢复指令
  2. 需响应暂停/恢复推流指令(OnVodStreamListener). 相应的暂停/恢复发送音视频数据.
/**
     * 收到暂停推流请求
     *
     * @param streamId 流ID
     */
    void onPausePushVodStreaming(int streamId);

    /**
     * 收到恢复推流的请求
     *
     * @param streamId 流ID
     */
    void onResumePushVodStreaming(int streamId);
  1. 处理Seek指令
  2. 需响应Seek指令(OnVodStreamListener). 例如: App端播放器进度条seek到80s时,对应会回调onSeekTo方法,请从该timeStampInS时间点最近的I帧开始继续推流.
/**
     * 收到重新定位请求
     *
     * @param streamId     流ID
     * @param timeStampInS 时间戳参数,单位为S
     */
    void onSeekTo(int streamId, long timeStampInS);
  1. 处理停止推流指令
  2. 当服务端下发停止推流请求时,回调OnVodStreamListener.onStopPushLiveStreaming()方法来通知设备端停止推流.
  3. 一般要停止调用发送音视频接口、关闭视频文件,并调用IPCStreamManager的stopStreaming(int streamId)方法.
/**
     * 收到停止推流请求
     *
     * @param streamId 流ID
     */
    @Override
    public void onStopPushStreaming(int streamId) {
        // TODO 停止音视频数据的发送
        try {
            // 调用停止推流接口
            IPCDev.getInstance().getIpcStreamManager().stopStreaming(streamId);
         catch (NoSuchStreamException e) {
            e.printStackTrace();
        }
    }
  1. 处理流错误
  2. 推流过程中需要处理流错误,通过OnStreamErrorListener.onError(int streamId, StreamError error)来接收和处理.

语音对讲

语音对讲支持双工模式. 设备端需要做音频采集-> 音频编码(可选)-> 上传/接收 -> 音频解码(可选) -> 音频播放 这些流程.

音频格式支持情况:

编码 解码
PCM - -
AAC_LC
G711A
G711U

语音对讲集成分为以下几个步骤:

  1. 注册语音对讲事件监听器和错误监听器
  2. IPC SDK收到服务端下发的语音对讲开始指令后,会通过事先注册的语音对讲事件监听器(OnLiveIntercomListener)来通知开始/结束语音对讲、接收对端的音频参数和语音数据. 推流中发生的错误也将通过错误监听器(OnLiveIntercomErrorListener)来通知. 注意回调接口中不要执行阻塞任务。
  3. 设置监听:
// 设置语音对讲事件监听
IPCDev.getInstance().getIpcLiveIntercom().setOnLiveIntercomListener(MainActivity.this);
// 设置语音对讲错误回调
IPCDev.getInstance().getIpcLiveIntercom().setOnLiveIntercomErrorListener(MainActivity.this);
public interface OnLiveIntercomListener {

    /**
     * 收到App端发起的开始语音对讲请求
     *
     * @return 返回当前设备端上行音频参数格式,如采样率、通道数、采样位宽、音频格式, 请确保对App端能支持该音频参数配置
     */
    AudioParams onStartVoiceIntercom();

    /**
     * 收到结束语音对讲请求
     */
    void onStopVoiceIntercom();

    /**
     * 收到App端音频参数
     * @param audioParams
     */
    void onAudioParamsChange(AudioParams audioParams);

    /**
     * 收到App端发送的音频数据
     * @param buffer
     * @param size
     */
    void onAudioBufferReceive(byte[] buffer, int size);
}
public interface OnLiveIntercomErrorListener {

    /**
     * 语音对讲发生错误
     * @param error 见{@link LiveIntercomError}
     */
    void onError(LiveIntercomError error);
}
  1. 响应开始语音对讲请求
    收到开始语音对讲请求后,需要启动录音机开始音频采集并将音频数据发送给对端.
@Override
    public AudioParams onStartVoiceIntercom() {
        appendLog("收到开始语音对讲指令");

        // 收到开始语音对讲请求, 启动录音机
        simpleAudioRecord.setAudioRecordListener(new AudioRecordListener() {
            @Override
            public void onRecordStart() {
                // 录音开始
                appendLog("录音开始");
            }

            @Override
            public void onRecordEnd() {
                // 录音结束
                appendLog("录音结束");
            }

            @Override
            public void onBufferReceived(byte[] buffer, int offset, int size) {
                // 收到录音机抛出的PCM数据, 调用发送接口发送给对端
                IPCDev.getInstance().getIpcLiveIntercom().sendAudioBuffer(buffer, offset, size);
            }

            @Override
            public void onError(int error, String message) {
                appendLog("录音机错误:" + error + " " + message);
            }
        });

        simpleAudioRecord.start();

        // 通知使用G711A作为音频发送格式,内部会对PCM数据重新做编码
        return AudioParams.AUDIOPARAM_MONO_8K_G711A;
    }

发送音频数据接口(IPCLiveIntercom):

/**
     * 发送音频数据<br>
     * 等价{@link #sendAudioBuffer(byte[] data, int offset, int length, boolean enableEncode)} enableEncode=true
     */
    void sendAudioBuffer(byte[] data, int offset, int length);

    /**
     * 发送音频数据<br>
     *
     * @param data         数据buffer
     * @param offset       偏移量
     * @param length       长度
     * @param enableEncode true: 内部会依据{@link OnLiveIntercomListener#onStartVoiceIntercom()}返回的音频格式对送入的数据(必须为PCM)重新编码并发送
     *                     false: 内部会直接发送音频数据
     */
    void sendAudioBuffer(byte[] data, int offset, int length, boolean enableEncode);
  1. 处理声音播放
  2. 当App端和设备端语音对讲通道建立后,设备端通过onAudioParamsChange(AudioParams audioParams)收到App端发过来的音频参数。依据该音频参数新建音频播放器,供后续接受的音频数据播放。
@Override
    public void onAudioParamsChange(AudioParams audioParams) {
        // 收到对端发送的音频参数
        appendLog("收到客户端的音频参数: " + audioParams.toString());

        // 初始化播放器
        if (simpleStreamAudioTrack != null) {
            simpleStreamAudioTrack.release();
            audioTrackQueue.clear();
        }
        if (acousticEchoCanceler != null) {
            acousticEchoCanceler.release();
        }
        if (noiseSuppressor != null) {
            noiseSuppressor.release();
        }
        noiseSuppressor = NoiseSuppressor.create(simpleAudioRecord.getAudioSessionId());
        if (noiseSuppressor != null) {
            noiseSuppressor.setEnabled(true);
        }
        simpleStreamAudioTrack = new SimpleStreamAudioTrack(audioParams, AudioManager.STREAM_MUSIC, audioTrackQueue,
                simpleAudioRecord.getAudioSessionId());
        if (AcousticEchoCanceler.isAvailable()) {
            acousticEchoCanceler = AcousticEchoCanceler.create(simpleAudioRecord.getAudioSessionId());
            if (acousticEchoCanceler != null) {
                appendLog("已开启回声消除");
                acousticEchoCanceler.setEnabled(true);
            }
        }

        simpleStreamAudioTrack.start();
    }


    @Override
    public void onAudioBufferReceive(byte[] buffer, int size) {
        // 收到对端发送的PCM数据
        audioTrackQueue.add(buffer);
    }
  1. 处理结束语音对讲指令
@Override
public void onStopVoiceIntercom() {
    appendLog("收到停止语音对讲指令");
    // 收到停止语音对讲请求,停止录音
    simpleAudioRecord.stop();
}
  1. 语音对讲错误处理
@Override
public void onError(LiveIntercomError error) {
    // 语音对讲发生错误
    appendLog("语音对讲错误:" + error.getCode() + " msg:" + error.getMessage());

    // 停止录音
    simpleAudioRecord.stop();

    // 停止播放
    simpleStreamAudioTrack.stop();
}

语音对讲错误列表:

错误码 错误描述
LiveIntercomError.INVALID_AUDIO_PARAMS 无效的设备端音频参数
LiveIntercomError.START_LIVE_INTERCOM_REQUEST_FAILED 无效的语音对讲请求
LiveIntercomError.CONNECTION_STREAM_FAILED 建立语音对讲流通道失败
LiveIntercomError.SEND_STREAM_DATA_FAILED 发送音频数据失败
LiveIntercomError.RECEIVE_STREAM_DATA_FAILED 接收音频数据失败

回声消除支持:
因为涉及到实时语音对讲,设备端必须要支持回声消除.
demo中使用的AcousticEchoCanceler设备相关性大,实际体验效果一般,仅供参考。

录音机与播放器:
IPC SDK提供了录音机(SimpleAudioRecord)和流音频播放器(SimpleStreamAudioTrack), 可用于语音对讲音频采集和播放.供参考。
SimpleAudioRecord

  • 创建录音机实例
/**

* 按照指定的音频参数创建录音机实例子

* @param audioSource 指定源

* @param audioParams 指定录音机的通道数、采样率、采样位宽

*/
SimpleAudioRecord(int audioSource, AudioParams audioParams);
  • 启动录音
void start();
  • 获取AudioSession id
int getAudioSessionId()
  • 设置录音事件回调
void setAudioRecordListener(AudioRecordListener listener)

public interface AudioRecordListener {

    /**
     * 开始录音
     */
    void onRecordStart();

    /**
     * 结束录音
     */
    void onRecordEnd();

    /**
     * 录音数据回调(PCM数据)
     * @param buffer
     * @param offset
     * @param size
     */
    void onBufferReceived(byte[] buffer, int offset, int size);

    /**
     * 录音机错误
     * {@link SimpleAudioRecord#ERR_INIT_RECORD}
     * {@link SimpleAudioRecord#ERR_READ_BUFFER}
     * {@link SimpleAudioRecord#ERR_START_RECORD}
     * @param error
     * @param message
     */
    void onError(int error, String message);
}
  • 结束录音
void stop();

SimpleStreamAudioTrack

  • 创建播放器实例
/**
     * 创建流播放器
     *
     * @param audioParams     音频参数
     * @param audioStreamType 流类型,见{@link android.media.AudioManager}
     * @param audioBuffer     数据阻塞队列,向该队列中加入数据即播放
     * @param audioSessionId  audio session id,用于回声消除
     * @throws IllegalArgumentException
     */
SimpleStreamAudioTrack(AudioParams audioParams, int audioStreamType, BlockingQueue audioBuffer) throws IllegalArgumentException;
  • 开始播放
void start()
  • 恢复播放
void resume()
  • 暂停播放
void pause()
  • 停止播放
void stop()
  • 获取播放状态,见AudioTrack#PLAYSTATE
int getPlayState()
  • 设置播放音量
void setVolume(float volume)
  • 释放播放器
void release()

图片上传

当前图片上传主要有两种:1.App端触发设备拍照,设备拍照后上传;2.设备端触发事件主动上报事件进行图片上传。
1.拍照上传
拍照上传任务大体流程是:通知设备拍照->设备拍照->拍照结果通知SDK->SDK完成上传图片->通知用户上传结果。
如果设备具有且需要集成拍照上传能力,那么用户需要注册对应的监听器:

/**
     * 注册拍照命令监听器.
     *
     * @param listener       备监听拍照命令的监听器
     * @param uploadListener 监听拍照任务结果的监听器,其能够获取上传照片是够成功
     */
IPCDev.getInstance().registerCaptureListener(ICaptureCommandListener listener,
                                        ICaptureProcessResultListener uploadListener)

其中ICaptureCommandListener为设备监听拍照命令的监听器,ICaptureProcessResultListener为监听拍照任务结果的监听器,其能够获取上传照片是否成功。ICaptureCommandListener需要用户实现,里面需要用户实现具体的拍照操作以及判断一个拍照任务是否执行。ICaptureCommandListener和ICaptureProcessResultListener监听器目前都各只支持一个,即如果用户注册了两个ICaptureCommandListener和两个ICaptureProcessResultListener,那么最后被注册上的ICaptureCommandListener和ICaptureProcessResultListener监听器才能收到消息。
示例:

IPCDev.getInstance().registerCaptureListener(new ICaptureCommandListener() {
                    @Override
                    public void onCapture(final ICaptureCallback callback) {
                        // TODO 添加拍照逻辑
                        if (callback != null) {
                            PicInfo picInfo = new PicInfo();
                            //将照片路径填入
                            picInfo.setFilePath(Environment.getExternalStorageDirectory()
                                        .getAbsolutePath() + "/2.jpeg");
                             //不设置这个值,默认图片格式为image/jpeg,
                             //如果是其他图片格式请设置,且格式满足MIME类型定义
                             picInfo.setFileType("image/jpeg");
                             callback.sendPic(picInfo);      
                        }
                    }

                    @Override
                    public boolean needProcess() {
                        //这个地方请根据当时设备是否能够拍照完成逻辑
                        //返回false则不进行此次处理,
                        //返回true则处理拍照事件,SDK会调用到capture(ICaptureCallback listener)
                        return true;
                    }
                }, new ICaptureProcessResultListener() {
                    @Override
                    public void onSucceed() {
                        //拍照上传成功                   
                        Log.d("ResultListener", "拍照上传成功!");
                    }

                    @Override
                    public void onFailed(String errorMsg) {
                         //拍照上传失败  
                        Log.e("ResultListener", "拍照上传失败!   " + errorMsg);
                    }
                });

2.事件上报
事件上报大体流程:设备触发事件->设备拍照->传信息给SDK->SDK完成图片以及事件上报。
事件上报接口:

/**
     * 上报报警事件.
     *
     * @param forceReport 是否强制上报,即图片传失败了是否需要上报报警事件
     * @param picInfo     报警图片信息
     * @param alarmType   报警类型,具体数值请参考物模型定义
     * @param listener    上报结果回调
     */
IPCDev.getInstance().reportAlarmEvent(final Boolean forceReport, PicInfo picInfo, 
                            final int alarmType, final ReportAlarmEventListener listener)

上报报警事件在SDK内分成两步:1.上传图片,2,上传报警。这些都在SDK内部实现用户不需要关心。
上报报警事件时,如果reportAlarmEvent的第一个参数forceReport为true,图片上报失败也会把报警进行上报,不过onFailed错误回调也会被调用,如果此时上传警报也失败了,那么onFailed会再次收到回调。即reportAlarmEvent的第一个参数为true时,一次上报报警事件,在最坏的情况下onFailed会被回调2次。第一次能知道上传图片的错误,第二次能获取上传警报的错误。
reportAlarmEvent的第一个参数forceReport为false时,一次上报报警事件,在最坏的情况下onFailed会被回调1次。回调通知上传图片的错误。即只要上传图片失败就不会上报事件。
例子:

PicInfo picInfo = new PicInfo();
//设置需要上传的图片路径。
picInfo.setFilePath(Environment.getExternalStorageDirectory()
                    .getAbsolutePath() + "/1.jpeg");
//不设置这个值,默认图片格式为image/jpeg;如果是其他图片格式,请设置图片格式,格式满足MIME类型定义
picInfo.setFileType("image/jpeg");
IPCDev.getInstance().reportAlarmEvent(true, picInfo, 1, new ReportAlarmEventListener() {
          @Override
          public void onSucceed() {
                Log.d(TAG, "上报事件成功");
          }

          @Override
          public void onFailed(String msg) {
                 Log.e(TAG, " 上报事件失败 e:" + msg);
          }
});

results matching ""

    No results matching ""