简介

EaseCallKit是一套基于环信IM和声网音视频结合开发的音视频UI库,实现了1v1语音通话、视频通话,以及多人音视频通话的功能, EaseCallKit可以快速实现一些通用的音视频功能。

注:本UI库只和移动端3.8.0以上版本Demo互通

跑通Demo

EaseCallKit集成在环信开源IMDemo中,你可以通过进入环信Demo及源码下载页面,选择Android端进行下载,直接下载: Android IM 源码

环境准备

  • Android Studio 3.2以上
  • Gradle4.6以上
  • targetVersion 26以上
  • Android SDK API 19以上
  • Java JDK 1.8以上

运行

  • 下载源码后,用Android Studio打开项目, 连接手机,然后就可以运行了

快速集成

以下展示如何快速集成EaseCallKit进行音视频通话的开发

在集成该库前,你需要满足以下条件:

  • 你已分别创建了环信应用及声网应用
  • 已完成环信IM的基本功能,包括登录、好友、群组以及会话等的集成
  • 上线之前开通声网token验证时,用户需要实现自己的AppServer,根据环信ID,生成Token,创建Token服务及使用AppServer生成Token的过程参见https://docs.agora.io/cn/live-streaming/token_server

使用EaseCallKitUI库完成音视频通话的基本流程如下:

  1. EaseCallKitUI库进行初始化并设置callkit监听(接口调用)
  2. 主叫方调用发起通话邀请接口,进入通话界面(接口调用)
  3. 被叫方收到邀请自动弹出通话邀请界面,在通话邀请界面选择接通或者拒绝(UI操作)
  4. 主叫或者被叫挂断通话(UI操作)

具体流程如下

导入UI库

EaseCallKitUI 主要依赖于com.hyphenate:hyphenate-chat:xxx版本,io.agora.rtc:full-sdk:xxx版本等库;

集成EaseCallKit库有两种方式,分别是 Gradle方式集成 和 Module源码集成

Gradle 方式集成

重大变动:远程仓库统一由JCenter迁移到MavenCentral,依赖库的域名由“com.hyphenate”修改为“io.hyphenate”,详见Android SDK 介绍及导入

  • 在build.gradle中增加以下内容,重新build 即可导入
implementation 'io.hyphenate:ease-call-kit:xxx版本'

EaseCallKitUI 必须依赖环信IM SDK(也就是hyphenate-chat) ,因而在使用EaseCallKitUI 时必须同时添加环信IM SDK依赖。

Module源码集成

implementation project(':ease-call-kit')

ease-call-kit中如果要修改hyphenate-chat和agora.rtc中版本号,可修改以下依赖

//环信SDK
implementation 'io.hyphenate:hyphenate-chat:xxx版本'  (hyphenate-chat 只支持3.8.0及以上版本)
//声网SDK
implementation 'io.agora.rtc:full-sdk:xxx版本'

添加权限

根据场景需要,本库需要增加 麦克风 相机 悬浮窗等权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.hyphenate.easeim">
 
    <!-- 悬浮窗权限 -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <!-- 访问网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 麦克风权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!-- 相机权限 -->
    <uses-permission android:name="android.permission.CAMERA" />
    ...
</manifest>

添加CallkitActivity

在清单中增加ease-call-kit 中的 EaseVideoCallActivity 和 EaseMultipleVideoActivity:

//增加 Activity
<activity
    android:name="com.hyphenate.easecallkit.ui.EaseVideoCallActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:excludeFromRecents="true"
    android:launchMode="singleInstance"
    android:screenOrientation="portrait"/>
<activity
    android:name="com.hyphenate.easecallkit.ui.EaseMultipleVideoActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:excludeFromRecents="true"
    android:launchMode="singleInstance"
    android:screenOrientation="portrait"/>

初始化

在环信IM SDK初始化完成后,可以开始初始化EaseCallKit,同时增加监听回调,设置常用配置项。代码如下:

//初始化 calluikit
EaseCallKitConfig callKitConfig = new EaseCallKitConfig();
//设置默认头像
String headImage = EaseFileUtils.getModelFilePath(context,"watermark.png");
callKitConfig.setDefaultHeadImage(headImage);
//设置振铃文件
String ringFile = EaseFileUtils.getModelFilePath(context,"huahai.mp3");
callKitConfig.setRingFile(ringFile);
//设置呼叫超时时间
callKitConfig.setCallTimeOut(30 * 1000);
//设置声网AgoraAppIdappId
callKitConfig.setAgoraAppId("*****");
Map<String, EaseCallUserInfo> userInfoMap = new HashMap<>();
userInfoMap.put("***",new EaseCallUserInfo("****",null));
userInfoMap.put("***",new EaseCallUserInfo("****",null));
callKitConfig.setUserInfoMap(userInfoMap);
EaseCallUIKit.getInstance().init(context,callKitConfig);
addCallkitListener();

可设置的配置项包括以下内容:

/**
 *
 * 有关callkit 用户配置选项
 * defaultHeadImage  用户默认头像(为本地文件绝对路径 或者url)
 * userInfoMap      有关用户信息(key为环信Id , value为EaseCallUserInfo);
 * callTimeOut      呼叫超时时间(单位ms 默认30s)
 * audioFile       震铃文件(本地文件绝对路径)
* enableRTCToken  是否需要RTC验证(需要声网后台去控制 默认为关闭)
 */
public class EaseCallKitConfig {
    private String defaultHeadImage;
    private Map<String,EaseCallUserInfo> userInfoMap = new HashMap<>();
    private String RingFile;
    private String agoraAppId = "****";
    private long callTimeOut = 30 * 1000;
    public EaseCallKitConfig(){
  ...
}

发起通话邀请

初始化完成后,可以发起音视频通话

1v1音视频通话

1v1通话可分为视频通话和语音通话,接口如下所示:

/**
* 加入1v1通话
* @param type 通话类型(只能为SIGNAL_VOICE_CALL或SIGNAL_VIDEO_CALL类型)
* @param user 被叫用户ID(也就是环信ID)
* @param ext  扩展字段(用户扩展字段)
*/
public void startSingleCall(final EaseCallType type, final String user,final  String ext){}

多人音视频通话

用户自己从群组成员列表或者好友列表中选择,发起多人音视频邀请,具体实现可参考demo中的 ConferenceInviteActivity 选择邀请人员列表及调用,接口如下所示:

/**
 * 邀请加入多人通话
 * @param users 用户ID列表(环信ID列表)
 * @param ext  扩展字段(用户扩展字段)
 */
public void startInviteMultipleCall(final String[] users,final String ext){}

发起通话后的UI界面如下:

被叫收到通话邀请

主叫方发起邀请后,如果被叫方在线,且当前不在通话中,将弹起邀请通话界面,可以选择接听或者拒绝,通话页面如下所示

被叫收到邀请后 会触发EaseCallKitListener中的以下回调:

/**
 * 收到通话邀请回调
 * @param callType  通话类型
 * @param userId   邀请方userId
 * @param ext     自定义扩展字段
 */
void onRevivedCall(EaseCallType callType, String userId,String ext){}

收到通话邀请后的界面如下

多人通话中邀请

多人通话中,当前用户可以再次向其他用户发起邀请。用户点击多人通话界面右上角的邀请按钮,

会触发EaseCallKitListener中的以下回调:

/**
 * 邀请好友进行多人通话
 * @param context
 * @param users   当前通话中已经存在的成员
 * @param ext     自定义扩展字段
 */
public void onInviteUsers(Context context,String userId[],String ext) {
}

1v1音视频通话中,对方挂断,本地会自动挂断结束,多人音视频通话中需要主动挂断才能结束通话,

通话结束后,会触发EaseCallKitListener中的以下回调:

通话结束

单人通话中,对方挂断,本地会自动挂断结束,多人通话中需要主动挂断才能结束通话。通话结束后,会触发以下回调

//**
 * 通话结束
 * @param callType    通话类型
 * @param reason     通话结束原因
 * @param callTime  通话时长
*/
void onEndCallWithReason(EaseCallType callType, String channelName, EaseCallEndReason reason, long callTime){}
 
//通话结束原因如下
public enum EaseCallEndReason {
    EaseCallEndReasonHangup(0), //正常挂断
    EaseCallEndReasonCancel(1), //自己取消通话
    EaseCallEndReasonRemoteCancel(2), //对方取消通话
    EaseCallEndReasonRefuse(3),//拒绝接听
    EaseCallEndReasonBusy(4), //忙线中
    EaseCallEndReasonNoResponse(5), //自己无响应
    EaseCallEndReasonRemoteNoResponse(6), //对端无响应
    EaseCallEndReasonHandleOnOtherDevice(7); //在其他设备处理
   ....
}

获取声网token

用户加入音视频时,需要获取声网token以进行鉴权,获取token的过程由用户自己完成,需要在EaseCallKitListener中把token回调给callkit

如果不需要鉴权,可以直接回调token 为null,或者不实现该回调, 具体接口和使用如下:

/**
 * 用户生成Token回调
 * @param userId       用户自己Id(环信Id)
 * @param channelName  频道名称
 * @param agoraAppId   声网appId
 * @param callback     生成的Token回调(成功为Token,失败为 errorCode和errorMsg)
 */
 default void onGenerateToken(String userId,String channelName,String agoraAppId,EaseCallKitTokenCallback callback){};
 
 @Override
 public void onGenerateToken(String userId, String channelName, String agoraAppId, EaseCallKitTokenCallback callback){
         if(callback != null){
               //demo中没有进行Token鉴权,所以传 null ,如果需要Token鉴权,则调用自己的AppServer生成Token,然后把生成的Token回调给callkit
               allback.onSetToken(null);
         }
}

通话异常回调

通话过程中如果有异常或者错误发生,会触发EaseCallKitListener中的以下回调:

/**
  * 通话错误回调
  * @param type            错误类型
  * @param errorCode      错误码
  * @param description   错误描述
*/
void onCallError(EaseCallUIKit.EaseCallError type, int errorCode, String description){}

EaseCallError异常包括业务逻辑异常,音视频异常以及业务逻辑异常,定义如下

/**
 * 通话错误类型
 *
*/
public enum EaseCallError{
   PROCESS_ERROR, //业务逻辑异常
   RTC_ERROR, //音视频异常
   IM_ERROR  //IM异常
}

配置修改

callkit库初始化之后,可以再次修改有关配置,接口和示例如下:

/**
* 获取当前callKitConfig
*
*/
public EaseCallKitConfig getCallKitConfig(){}
 
//如修改配置默认头像
EaseCallKitConfig config = EaseCallUIKit.getInstance().getCallKitConfig();
if(config != null){
     String Image = EaseFileUtils.getModelFilePath(context,"bryant.png");
     callKitConfig.setDefaultHeadImage(Image);
}

离线推送

为保证被叫用户APP退到后台,或离线时也能收到通话请求,用户需要开启离线推送,离线推送场景方案参见:http://docs-im.easemob.com/im/other/integrationcases/iosimnotifi

离线推送开启过程参见:推送集成

开启离线推送后,被叫用户在离线情况下收到呼叫请求时,会在手机通知页面弹出一条通知消息,用户点击该消息,可以唤醒App,并进入振铃页面

EaseCallKit中提供的接口如下

方法 说明

init 初始化方法
setCallKitListener 设置监听
startSingleCall 发起单人通话
startInviteMultipleCall 发起多人通话
getCallKitConfig 获取有关配置

回调模块EaseCallKitListener的API列表如下

事件 说明
onEndCallWithReason 通话结束时触发该事件
onInviteUsers 多人会议中点击邀请按钮触发该事件
onRevivedCall 振铃时触发该事件
onGenerateToken 获取声网token回调,用户自己获取到Token, 把Token回调到callkit
onCallError 通话异常时触发该回调
onInViteCallMessageSent 通话邀请消息回调