差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
im:android:basics:audiovideo [2020/02/06 06:19] huanxinfudh [监听通话状态] |
— (当前版本) | ||
---|---|---|---|
行 1: | 行 1: | ||
- | ====== 实时通话 ====== | ||
- | |||
- | ---- | ||
- | |||
- | 实时通话分为视频通话和音频通话,与普通电话不同,它是基于网络的。 | ||
- | |||
- | ===== 实时通话的数据流量 ===== | ||
- | |||
- | 实时语音和实时视频的数据流量如下: | ||
- | |||
- | 实时语音: | ||
- | * 双向 170k bytes/minute | ||
- | 实时视频(单路): | ||
- | * 240p: 0.75M ~ 3M | ||
- | * 480p: 2.2M ~ 7.5M | ||
- | * 720p: 6.5M ~ 18.5M | ||
- | * 1080p: 15M ~ 37.5M | ||
- | |||
- | ===== 监听呼入通话 ===== | ||
- | |||
- | 通过注册相应 action 的 BroadcastReceiver 来监听呼叫过来的通话,接到广播后开发者可以调起 APP 里的通话 Activity。 | ||
- | |||
- | <code java> | ||
- | IntentFilter callFilter = new IntentFilter(EMClient.getInstance().callManager().getIncomingCallBroadcastAction()); | ||
- | registerReceiver(new CallReceiver(), callFilter); | ||
- | |||
- | private class CallReceiver extends BroadcastReceiver { | ||
- | |||
- | @Override | ||
- | public void onReceive(Context context, Intent intent) { | ||
- | // 拨打方username | ||
- | String from = intent.getStringExtra("from"); | ||
- | // call type | ||
- | String type = intent.getStringExtra("type"); | ||
- | //跳转到通话页面 | ||
- | |||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | ===== 监听通话状态 ===== | ||
- | |||
- | 通过 addCallStateChangeListener 监听通话状态。 | ||
- | |||
- | **注意:**在收到 DISCONNECTED 回调时才能 finish 当前页面(保证通话所占用的资源都释放完),然后开始下一个通话。 | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().addCallStateChangeListener(new EMCallStateChangeListener() { | ||
- | @Override | ||
- | public void onCallStateChanged(CallState callState, CallError error) { | ||
- | switch (callState) { | ||
- | case CONNECTING: // 正在连接对方 | ||
- | |||
- | break; | ||
- | case CONNECTED: // 双方已经建立连接 | ||
- | |||
- | break; | ||
- | |||
- | case ACCEPTED: // 电话接通成功 | ||
- | |||
- | break; | ||
- | case DISCONNECTED: // 电话断了 | ||
- | |||
- | break; | ||
- | case NETWORK_UNSTABLE: //网络不稳定 | ||
- | if(error == CallError.ERROR_NO_DATA){ | ||
- | //无通话数据 | ||
- | }else{ | ||
- | } | ||
- | break; | ||
- | case NETWORK_NORMAL: //网络恢复正常 | ||
- | |||
- | break; | ||
- | case NETWORK_DISCONNECTED: //通话中对方断开连接会执行 | ||
- | |||
- | break; | ||
- | default: | ||
- | break; | ||
- | } | ||
- | |||
- | } | ||
- | }); | ||
- | </code> | ||
- | |||
- | 详细回调请参考[[http://www.easemob.com/apidoc/android/chat3.0/annotated.html|API Doc]]。 | ||
- | |||
- | ===== 拨打语音通话 ===== | ||
- | |||
- | <code java> | ||
- | /** | ||
- | * 拨打语音通话 | ||
- | * @param to | ||
- | * @throws EMServiceNotReadyException | ||
- | */ | ||
- | try {//单参数 | ||
- | EMClient.getInstance().callManager().makeVoiceCall(username); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | try {//多参数 | ||
- | EMClient.getInstance().callManager().makeVoiceCall(username,"ext 扩展内容"); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | try {//多参数, recordOnServer:是否在服务器端录制该通话, mergeStream:服务器端录制时是否合并流 | ||
- | EMClient.getInstance().callManager().makeVoiceCall(username,"ext 扩展内容", recordOnServer, mergeStream); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | //获取扩展内容 | ||
- | String callExt = EMClient.getInstance().callManager().getCurrentCallSession().getExt(); | ||
- | </code> | ||
- | |||
- | ===== 拨打视频通话 ===== | ||
- | |||
- | <code java> | ||
- | /** | ||
- | * 拨打视频通话 | ||
- | * @param to | ||
- | * @throws EMServiceNotReadyException | ||
- | */ | ||
- | try {//单参数 | ||
- | EMClient.getInstance().callManager().makeVideoCall(username); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | try {//多参数 | ||
- | EMClient.getInstance().callManager().makeVideoCall(username,"ext 扩展内容"); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | try {//多参数, recordOnServer:是否在服务器端录制该通话, mergeStream:服务器端录制时是否合并流 | ||
- | EMClient.getInstance().callManager().makeVideoCall(username,"ext 扩展内容", recordOnServer, mergeStream); | ||
- | } catch (EMServiceNotReadyException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | |||
- | //获取扩展内容 | ||
- | String callExt = EMClient.getInstance().callManager().getCurrentCallSession().getExt(); | ||
- | </code> | ||
- | |||
- | 视频通话需要显示自己和对方的图像,需要[[#视频通话设置显示自己和对方图像的surfaceView|设置相应 surfaceview]]。 | ||
- | |||
- | ===== 接听通话 ===== | ||
- | |||
- | <code java> | ||
- | /** | ||
- | * 接听通话 | ||
- | * @throws EMNoActiveCallException | ||
- | * @throws EMNetworkUnconnectedException | ||
- | */ | ||
- | try { | ||
- | EMClient.getInstance().callManager().answerCall(); | ||
- | } catch (EMNoActiveCallException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } catch (EMNetworkUnconnectedException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | </code> | ||
- | |||
- | ===== 拒绝接听 ===== | ||
- | |||
- | <code java> | ||
- | /** | ||
- | * 拒绝接听 | ||
- | * @throws EMNoActiveCallException | ||
- | */ | ||
- | try { | ||
- | EMClient.getInstance().callManager().rejectCall(); | ||
- | } catch (EMNoActiveCallException e) { | ||
- | // TODO Auto-generated catch block | ||
- | e.printStackTrace(); | ||
- | } | ||
- | </code> | ||
- | |||
- | ===== 挂断通话 ===== | ||
- | |||
- | <code java> | ||
- | /** | ||
- | * 挂断通话 | ||
- | */ | ||
- | EMClient.getInstance().callManager().endCall(); | ||
- | </code> | ||
- | |||
- | ===== 暂停和恢复语音或视频数据传输 ===== | ||
- | |||
- | 暂停语音数据传输: | ||
- | |||
- | ''EMClient.getInstance().callManager().pauseVoiceTransfer()'' | ||
- | |||
- | 恢复语音数据传输: | ||
- | |||
- | ''EMClient.getInstance().callManager().resumeVoiceTransfer()'' | ||
- | |||
- | 暂停视频(图像)数据传输: | ||
- | |||
- | ''EMClient.getInstance().callManager().pauseVideoTransfer()'' | ||
- | |||
- | 恢复视频(图像)数据传输: | ||
- | |||
- | ''EMClient.getInstance().callManager().resumeVideoTransfer()'' | ||
- | |||
- | **调用后对方会收到相应VOICE_PAUSE、VOICE_RESUME、VIDEO_PAUSE、VIDEO_RESUME的callstate的变动通知。** | ||
- | |||
- | ===== 视频通话设置显示自己和对方图像的 surfaceView ===== | ||
- | |||
- | 视频通话需要预先设置 localSurfaceView、oppositeSurfaceView, | ||
- | 而且必须在''Activity.onCreate(Context context)''方法中设置,之后才能正确捕捉 Surface 的变化。 | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().setSurfaceView(localSurface, oppositeSurface); | ||
- | </code> | ||
- | |||
- | ===== 视频通话处理本地摄像头数据 ===== | ||
- | 如果需要处理自己本地视频数据,比如美颜等操作,可以自己输入视频数据进行操作,原来的回调视频数据接口''EMCameraDataProcessor''已经废弃,不推荐使用; | ||
- | |||
- | 使用方式: | ||
- | <code java> | ||
- | /** | ||
- | * 首先在初始化音视频部分设置外部输入视频数据 | ||
- | * 设置是否启用外部输入视频数据,默认 false,如果设置为 true,需要自己调用 | ||
- | * {@link EMCallManager#inputExternalVideoData(byte[], int, int, int)}输入视频数据 | ||
- | */ | ||
- | EMClient.getInstance().callManager().getCallOptions().setEnableExternalVideoData(true); | ||
- | ... | ||
- | /** | ||
- | * 然后就是自己获取视频数据,进行美颜等处理,循环调用以下方法输入数据就行了(这个调用频率就相当于你的帧率,调用间隔可以自己进行控制,一般最大30帧/秒) | ||
- | * 视频数据的格式是摄像头采集的格式即:NV21 420sp 自己手动传入时需要将自己处理的数据转为 yuv 格式输入 | ||
- | */ | ||
- | EMClient.getInstance().callManager().inputExternalVideoData(data, width, height, rotate); | ||
- | </code> | ||
- | |||
- | ===== 切换摄像头 ===== | ||
- | |||
- | 视频通话时如果有前置摄像头,默认使用前置的,提供切换 API 切换到别的摄像头。 | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().switchCamera(); | ||
- | </code> | ||
- | |||
- | ===== 更多视频通话相关 API ===== | ||
- | |||
- | 视频通话相对复杂,把视频相关的一些 API 封装到了 EMVideoCallHelper 里。 | ||
- | |||
- | ==== 获取 CallHelper ==== | ||
- | |||
- | <code java> | ||
- | EMVideoCallHelper callHelper = EMClient.getInstance().callManager().getVideoCallHelper(); | ||
- | </code> | ||
- | |||
- | ==== 设置通话最大帧率 ==== | ||
- | |||
- | 设置通话最大帧率,SDK 最大支持(30),默认(20) | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().getCallOptions().setMaxVideoFrameRate(30); | ||
- | </code> | ||
- | |||
- | ==== 设置图像分辨率 ==== | ||
- | |||
- | 设置视频通话分辨率 默认是(640, 480) | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().getCallOptions().setVideoResolution(640, 480); | ||
- | </code> | ||
- | |||
- | ==== 设置视频比特率 ==== | ||
- | |||
- | 设置视频通话最大和最小比特率(可以不设置,SDK会根据手机分辨率和网络情况自动适配),最大值默认800, 最小值默认80 | ||
- | |||
- | <code java> | ||
- | |||
- | EMClient.getInstance().callManager().getCallOptions().setMaxVideoKbps(800); | ||
- | EMClient.getInstance().callManager().getCallOptions().setMinVideoKbps(80); | ||
- | |||
- | </code> | ||
- | |||
- | ==== 离线推送 ==== | ||
- | |||
- | 音视频呼叫对方,如果对方不在线,则发送一条离线消息通知对方(true推送,false不推送) | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().getCallOptions().setIsSendPushIfOffline(false); | ||
- | </code> | ||
- | |||
- | |||
- | ==== 音视频采样率 ==== | ||
- | |||
- | 设置音视频采样率,一般不需要设置,除非采集声音有问题才需要手动设置(默认值48000),根据自己硬件设备确定 | ||
- | |||
- | <code java> | ||
- | EMClient.getInstance().callManager().getCallOptions().setAudioSampleRate(48000); | ||
- | </code> | ||
- | |||
- | ==== 设置音频源 ==== | ||
- | 设置音视频通话时音频源,参数表示采集语音时所设置的音频源类型(这个一般只有在外接输入源时才需要设置),具体值参考 ''MediaRecorder.AudioSource'' 源码类,SDK 中默认值 VOICE_COMMUNICATION | ||
- | <code java> | ||
- | EMClient.getInstance().callManager().getCallOptions().setCallAudioSource(AudioSource.MIC); | ||
- | </code> | ||
- | |||
- | |||
- | |||
- | 详细文档请参考 [[im:android:sdk:apidoc|Java Doc]]。 | ||
- | |||
- | |||
- | ---- | ||
- | <WRAP group> | ||
- | <WRAP half column> | ||
- | 上一页:[[im:android:basics:chatroom|聊天室管理]] | ||
- | </WRAP> | ||
- | |||
- | <WRAP half column> | ||
- | 下一页:[[im:android:basics:multiuserconference|多人音视频会议]] | ||
- | </WRAP> | ||
- | </WRAP> | ||