跳到主要内容

实现首次通话

适用于 Android 的 CallPlus 可在您的应用程序中为用户之间的一对一和多人通信提供语音和视频通话能力。

CallPlus 支持 一对一通话多人通话。按照下面的指南使用 Java 或 Kotlin 从头开始实现一对一通话和多人通话。


环境要求

适用于 Android 的 CallPlus SDK 的最低要求是:

  • Android 5 (API level 21) or higher
  • Java 8 or higher

前置条件

  • 注册开发者账号。注册成功后,控制台会默认自动创建您的首个应用,默认生成开发环境下的 App Key,使用国内数据中心。

  • 获取开发环境的应用 App Key。如不使用默认应用,请参考 如何创建应用,并获取对应环境 App Key 和 App Secret

    注意

    每个应用具有两个不同的 App Key,分别对应开发环境与生产环境,两个环境之间数据隔离。在您的应用正式上线前,可切换到使用生产环境的 App Key,以便上线前进行测试和最终发布。

  • 完成开通音视频服务。您需要开通音视频通话服务。


Demo 项目

融云提供了一个 Android 端 Demo 项目,集中演示了通话、会议、直播场景下的功能。

https://github.com/rongcloud/rtc-quickdemo-android


快速上手

您可以通过安装 CallPlus for Android 进行一对一通话,或多人通话。

步骤 1 创建项目

首先,打开 Android Studio 并在 Project 窗口中创建一个新项目,如下所示:

  1. Welcome to Android Studio 窗口中点击 Start a new Android Studio project
  2. 选择 Empty Activity,接着点击 Next
  3. Name 字段中输入您的项目名称。
  4. 从语言下拉菜单中选择您的语言 Java or Kotlin
  5. 选择最低 API 级别为 21 或更高。

(width=800)


步骤 2 导入 SDK

Gradle

使用 Gradle,添加融云音视频通话能力库 CallPlus 为远程依赖项。请注意使用 融云的 Maven 仓库

  1. 打开根目录下的 build.gradleProject 视图下),声明融云的 Maven 代码库。

    allprojects {
    repositories {
    ...
    //融云 maven 仓库地址
    maven {url "https://maven.rongcloud.cn/repository/maven-releases/"}
    }
    }
  2. 在应用的 build.gradle 中,添加对 IMLibCore 和 CallPlus 的远程依赖项。融云 CallPlus 业务依赖 IM 通道,所以必须同时集成 IMLibCore SDK(最低使用 5.6.3 版本)。

    dependencies {
    // x.y.z,请填写具体的 SDK 版本号,新集成用户建议使用最新版。
    implementation 'cn.rongcloud.sdk:im_libcore:x.y.z' // 即时通讯基础能力库。
    implementation 'cn.rongcloud.sdk:callplus_lib:x.y.z'// 音视频呼叫能力库
    implementation 'cn.rongcloud.sdk:rtc_lib:x.y.z' // 音视频通话基础能力库
    }

注意

各个 SDK 的最新版本号可能不相同,还可能是 x.y.z.h,可前往 融云官网 SDK 下载页面融云的 Maven 代码库 查询。 自 2.1.1 版本起,callplus_lib 内不再包含 rtc_lib。在使用 callplus_lib 的同时,还需要引入 rtc_lib。

Android 本地库模块 (Module)

在导入 SDK 前,您需要前往融云官网 SDK 下载页面,将音视频通话能力-CallPlusLib及其依赖的即时通讯能力库-IMLib音视频基础能力-RTCLib 下载到本地。

  1. rong_callplus_x.y.z.aar 文件复制到 Android Studio 项目的 libs 目录下,在应用的 build.gradle 中,添加 *.aar 依赖。

  2. 依次点击 File > New > Import Module,将 imlibrtclib 的 Module 组件导入。

    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
    implementation project(path: ':imlib')
    implementation project(path: ':rtclib')
    }

步骤 3 权限配置

  1. 在 AndroidManifest.xml 中声明 SDK 需要的所有权限。

    <!-- 允许程序访问网络连接 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 允许程序获取网络信息状态,如当前的网络连接是否有效 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <!-- 允许程序获取当前WiFi接入的状态以及WLAN热点的信息 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!-- 允许程序访问摄像头进行拍照 -->
    <uses-permission android:name="android.permission.CAMERA" />
    <!-- 允许程序录制声音通过手机或耳机的麦克 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!-- 允许程序修改声音设置信息 -->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <!--允许程序访问电话状态,如通话中收到来自SIM卡的来电时,会将SIM卡通话状态通知给远端用户,所以需要该权限-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  2. 如果您的应用需要支持 Android 6.0(API 级别 23)或更高版本的设备,您还需要在 App 用户使用对应功能时(例如发起呼叫、接听)请求摄像头(CAMERA)、麦克风(RECORD_AUDIO)权限。详见 Android 开发者官方文档运行时权限请求权限的工作流


步骤 4 代码混淆

当您使用 minifyEnabled true 构建 APK 时,将以下行添加到模块的 ProGuard 规则文件中。

-keepattributes Exceptions,InnerClasses

-keepattributes Signature

# imlib
-keep class io.rong.** {*;}
-keep class cn.rongcloud.** {*;}
-keep class * implements io.rong.imlib.model.MessageContent {*;}
-dontwarn io.rong.push.**
-dontnote com.xiaomi.**
-dontnote com.google.android.gms.gcm.**
-dontnote io.rong.**

#rtclib
-keep public class cn.rongcloud.rtc.** {*;}
-keep public class cn.rongcloud.rtclib.** {*;}

#callpluslib
-keep public class cn.rongcloud.calllib.** {*;}
-keep public class cn.rongcloud.callplus.** {*;}

-ignorewarnings

步骤 5 使用 App Key 初始化

CallPlus for Android 是依赖融云即时通讯客户端 SDK 提供信令通道。要在您的应用程序中集成和运行,您需要先对 IMLibCore 进行初始化。

融云即时通讯客户端 SDK 核心类为 RongCoreClientRongIMClient。在 Application 的 onCreate() 方法中,调用 RongCoreClient 的初始化方法,传入生产开发环境的 App Key。

String appKey = "Your_AppKey"; // example: bos9p5rlcm2ba
InitOption initOption = new InitOption.Builder().build();

RongCoreClient.init(getApplicationContext(), appKey, initOption);

初始化配置(InitOption)中封装了区域码(AreaCode),导航服务地址(naviServer)、文件服务地址(fileServer)、数据统计服务地址(statisticServer)配置,以及是否开启推送的开关(enablePush)和主进程开关(isMainProcess)。您可以传 null,表示全部使用默认配置。SDK 默认连接北京数据中心。

如果 App Key 不属于中国(北京)数据中心,则必须传入有效的初始化配置。


步骤 6 添加通话所需监听

使用 setCallPlusEventListener 方法添加通话事件监听 IRCCallPlusEventListener。该监听提供来电事件、通话状态、通话记录等事件相关回调。通过 setCallPlusEventListener(null); 可移除监听器。

注意

如果未注册 IRCCallPlusEventListener 监听器,则用户无法接收 onReceivedCall 回调事件。请务必在下一步与融云服务器建立连接(connect)之前使用 setCallPlusEventListener 注册监听,否则用户在未连接的情况下无法通过离线推送接收来电通知。

RCCallPlusClient.getInstance().setCallPlusEventListener(new IRCCallPlusEventListener() {

/**
* 本端用户通过该回调接收到通话呼叫
*
* @param callSession 通话实体信息
*/
@Override
public void onReceivedCall(RCCallPlusSession callSession, String extra) {
RCCallPlusSession currentCallSession = RCCallPlusClient.getInstance().getCurrentCallSession();
if (currentCallSession != null && !TextUtils.equals(callSession.getCallId(), currentCallSession.getCallId())) {
//可以使用该方法判断出,有正在进行中的通话,又有第二通通话呼入的情况
//todo 第二通通话可以直接调用 RCCallPlusClient.getInstance().accept 方法接听,SDK内部会将第一通通话挂断
}

//todo SDK 的回调均为子线程调用
// showDialog() 方法中存在UI操作,所以切换到主线程执行
// showDialog() 方法实现可参考附录
runOnUiThread(new Runnable() {
@Override
public void run() {
//todo 打开摄像头采集,请提前完成摄像头、麦克风权限的动态申请
RCCallPlusClient.getInstance().startCamera();
RCCallPlusClient.getInstance().enableMicrophone(true);

setLocalVideoView();//复用发起通话逻辑中的 设置本地视频渲染视图 方法

showDialog(CallPlusActivity.this, "收到通话,是否接听?", "接听", new OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
acceptCall(callSession);
}
}, "挂断", new OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
RCCallPlusClient.getInstance().hangup();
}
});
}
});
}

@Override
public void onCallEnded(RCCallPlusSession session, RCCallPlusReason reason) {
IRCCallPlusEventListener.super.onCallEnded(session, reason);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(CallPlusActivity.this,"通话结束,callId: "+session.getCallId() +" 通话结束原因:"+ reason.getValue(), Toast.LENGTH_SHORT).show();
}
});
}

/**
* 远端用户状态改变监听
*
* @param callId 通话Id
* @param userId 用户Id
* @param status 该用户当前状态
* @param reason 该用户当前状态原因
*/
@Override
public void onRemoteUserStateChanged(String callId, String userId, RCCallPlusUserSessionStatus status, RCCallPlusReason reason) {
IRCCallPlusEventListener.super.onRemoteUserStateChanged(callId, userId, status, reason);
runOnUiThread(new Runnable() {
@Override
public void run() {
StringBuilder stringBuilder = new StringBuilder("通话 ");
stringBuilder.append(callId).append(" 中的远端用户 ").append(userId).append(" 当前状态为 ");
switch (status) {
case IDLE:
stringBuilder.append("空闲");
break;
case CALLING:
stringBuilder.append("呼叫中");
break;
case INVITED:
stringBuilder.append("被邀请中");
break;
case RINGING:
stringBuilder.append("响铃中");
break;
case BUSY_LINE_RINGING:
stringBuilder.append("忙线(响铃中)");
break;
case BUSY_LINE_WAIT:
stringBuilder.append("忙线(通话中)");
break;
case CONNECTING:
stringBuilder.append("已接听,连接中");
break;
case ON_CALL:
stringBuilder.append("通话中");
break;
case ENDED:
stringBuilder.append("通话已结束");
break;
case NO_ANSWER:
stringBuilder.append("未应答");
break;
case MISSED:
stringBuilder.append("未接听");
break;
case CANCELED:
stringBuilder.append("已取消");
break;
case DECLINED:
stringBuilder.append("已拒绝");
break;
case ERROR:
stringBuilder.append("错误");
break;
}
Toast.makeText(CallPlusActivity.this, stringBuilder.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});

使用 setCallPlusResultListener 方法添加通话 API 异步结果回调监听 IRCCallPlusResultListener。该监听可以接收 startCallaccepthangup 等方法的结果回调。通过 setCallPlusResultListener(null); 可移除监听器。

RCCallPlusClient.getInstance().setCallPlusResultListener(new IRCCallPlusResultListener() {

/**
* 发起通话方法结果回调
*
* @param code 方法请求结果
* @param callId 通话Id
* @param busyUserList 呼叫成功后,返回被邀请人列表中的忙线用户列表
*/
@Override
public void onStartCall(RCCallPlusCode code, String callId, List<RCCallPlusUser> busyUserList) {
IRCCallPlusResultListener.super.onStartCall(code, callId, busyUserList);
}

/**
* 接听通话结果回调
*
* @param code 方法请求结果
* @param callId 通话Id
*/
@Override
public void onAccept(RCCallPlusCode code, String callId) {
IRCCallPlusResultListener.super.onAccept(code, callId);
}

/**
* 挂断指定通话结果回调
*
* @param code 方法请求结果
* @param callId 通话Id
*/
@Override
public void onHangup(RCCallPlusCode code, String callId) {
IRCCallPlusResultListener.super.onHangup(code, callId);
}
});

步骤 7 获取用户 Token

用户身份令牌(Token)与用户 ID 对应,是应用程序用户在融云的唯一身份标识。应用客户端在使用融云服务前必须与融云建立 IM 连接,连接时必须传入 Token。

在体验和调试阶段,我们将使用控制台「北极星」开发者工具箱,从 API 调试页面调用 获取 Token 接口,获取到 userId 为 1 的用户的 Token。提交后,可在返回正文中取得 Token 字符串。

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"code":200,"userId":"1","token":"gxld6GHx3t1eDxof1qtxxYrQcjkbhl1V@sgyu.cn.example.com;sgyu.cn.example.com"}

融云的客户端 SDK 不提供获取 token 的 API。在实际业务运行过程中,调用融云 Server API /user/getToken.json,传入您的应用分配的用户标识(userId)申请 Token。详见 Server API 文档 注册用户


步骤 8 连接融云服务器

要拨打和接听一对一对呼叫或开始多人呼叫,必须先通过 RongCoreClientconnect 方法连接融云服务器,传入用户身份令牌(Token),向融云服务器验证用户身份。连接成功后,使用 RCCallPlusClient.getInstance().init() 方法初始化和配置 CallPlus SDK。

注意

必须在连接成功之后调用 RCCallPlusClient.getInstance().init 方法初始化 CallPlus SDK。反初始化使用 RCCallPlusClient.getInstance().unInit(); 方法。

String token = "用户Token";
RongCoreClient.connect(token, new IRongCoreCallback.ConnectCallback() {
/**
* 成功回调
* @param userId 当前用户 ID
*/
@Override
public void onSuccess(String userId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//todo 尽管在主线程初始化 RCCallPlusClient 不是必需的,但考虑到代码示例后续对 RCCallPlusClient 的调用都在主线程进行,所以目前选择在主线程进行初始化。
//todo 请确保在同一个线程进行 RCCallPlusClient 的初始化、反初始化和使用,以确保操作的一致性。
RCCallPlusConfig config = RCCallPlusConfig.Builder.create().build();
/**
* 初始化并设置通话全局配置,重复调用该方法时SDK内部会重新初始化
* @param config 设置通话全局配置
* @return 方法调用后同步返回结果,可以在这里得到初始化是否成功
*/
RCCallPlusResultCode resultCode = RCCallPlusClient.getInstance().init(config);
}
});

}
/**
* 错误回调
* @param errorCode 错误码
*/
@Override
public void onError(IRongCoreEnum.ConnectionErrorCode errorCode) {

}

/**
* 数据库回调.
* @param code 数据库打开状态. DATABASE_OPEN_SUCCESS 数据库打开成功; DATABASE_OPEN_ERROR 数据库打开失败
*/
@Override
public void onDatabaseOpened(DatabaseOpenStatus code) {

}
});

进行一对一通话

CallPlus for Android 定义了仅限两位用户通话的一对一通话类型 RCCallPlusType.PRIVATE。发起一对一类型通话时,只允许传入一个被叫用户 ID,仅在被叫接听成功后才会建立通话。融云会在被叫接听成功后开始计时计费。

本节中将简单介绍如何发起一对一通话,如何接收来电,以及通话接通后双方通话界面如何显示。

步骤 9 拨打

注意

从 CallPlus 2.0 开始,新增 startCall 重载方法,支持在发起呼叫时通过配置推送属性自定义远程推送标题等属性。支持携带自定义数据。

您可以使用 startCall 方法来发起一对一通话。该方法调用后,SDK 内部会以异步方式执行。在主叫与被叫端触发以下回调:

如果远端被叫用户接听通话,本地主叫用户将通过 IRCCallPlusEventListeneronRemoteUserStateChanged 回调获取到该用户状态变更,其中 RCCallPlusUserSessionStatus 枚举为 CONNECTING 时表示用户已经接听,正在连接中。

private void startCall(String remoteUserId) {
//todo 打开摄像头采集,请提前完成摄像头、麦克风权限的动态申请
RCCallPlusClient.getInstance().startCamera();
RCCallPlusClient.getInstance().enableMicrophone(true);

setLocalVideoView();

//创建远端视图对象 remoteUserId为远端用户userId
RCCallPlusRemoteVideoView remoteVideoView = new RCCallPlusRemoteVideoView(remoteUserId, this.getApplicationContext(), false);
//FIT: 视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小
remoteVideoView.setRenderMode(RCCallPlusRenderMode.FIT);
//因为远端视图显示在最顶层,为了防止远端视频视图被底部控件遮挡,所以添加如下设置:
remoteVideoView.setZOrderOnTop(true);
remoteVideoView.setZOrderMediaOverlay(true);

List<RCCallPlusRemoteVideoView> remoteVideoViewList = new ArrayList<>(); remoteVideoViewList.add(remoteVideoView);
//设置远端视图给SDK
RCCallPlusClient.getInstance().setVideoView(remoteVideoViewList);

FrameLayout.LayoutParams remoteVideoViewParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
remoteVideoViewParams.gravity = Gravity.CENTER_HORIZONTAL;
//将远端视图添加到XML中显示
//示例代码中 mRemoteVideoViewFrameLayout 为 android.widget.FrameLayout 对象
mRemoteVideoViewFrameLayout.removeAllViews();
mRemoteVideoViewFrameLayout.addView(remoteVideoView, remoteVideoViewParams);

List<String> userIds = new ArrayList<>();
userIds.add(remoteUserId);//todo remoteUserId 为被呼叫的远端用户userId
RCCallPlusType callType = RCCallPlusType.PRIVATE;//PRIVATE: 1V1通话
RCCallPlusMediaType mediaType = RCCallPlusMediaType.VIDEO;
RCCallPlusPushConfig pushConfig = RCCallPlusPushConfig.Builder
.create()
.build();

/**
* 开始发起呼叫
* 该方法内部为异步执行,结果回调是注册的{@link RCCallPlusClient#setCallPlusResultListener(IRCCallPlusResultListener)} 监听的 {@link IRCCallPlusResultListener#onStartCall(RCCallPlusCode, String, List)}方法
*/
RCCallPlusClient.getInstance().startCall(userIds, callType, mediaType, pushConfig, "extra");

}

实现 setLocalVideoView 方法,调用 CallPlus SDK 的 setVideoView 方法,传入 RCCallPlusLocalVideoView,设置本地摄像头渲染视图。

 /**
* 设置本地视频渲染视图
*/
private void setLocalVideoView() {
//创建本地视图对象
RCCallPlusLocalVideoView localVideoView = new RCCallPlusLocalVideoView(this.getApplicationContext());
//FIT: 视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小
localVideoView.setRenderMode(RCCallPlusRenderMode.FIT);
//设置本地视图给SDK
RCCallPlusClient.getInstance().setVideoView(localVideoView);

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER_HORIZONTAL;//在父布局中横向居中显示
//将本地视图添加到XML中显示
//示例代码中 mLocalVideoViewFrameLayout 为 android.widget.FrameLayout 对象
mLocalVideoViewFrameLayout.removeAllViews();
mLocalVideoViewFrameLayout.addView(localVideoView, params);
}

步骤 10 接听

重要

非兼容性变更:从 CallPlus 2.0 开始,onReceivedCall 方法发生非兼容变更,新的方法会携带 extra 字段。请您在升级时注意修改相关代码。

被叫用户可以选择接听来电 accept 或挂断来电 hangup。执行接听和挂断操作所需传入的 callId 值,可以通过 RCCallPlusSessiongetCallId() 方法获取。

private void acceptCall(RCCallPlusSession callSession) {
setRemoteUserVideoView(callSession.getRemoteUserList());

/**
* 开始接听通话
* 该方法内部为异步执行,结果回调是注册的{@link RCCallPlusClient#setCallPlusResultListener(IRCCallPlusResultListener)} 监听的 {@link IRCCallPlusResultListener#onAccept(RCCallPlusCode, String)}方法
*/
RCCallPlusClient.getInstance().accept(callSession.getCallId());
}

要接收远端呼叫通知,必须已注册 IRCCallPlusEventListener,并实现 onReceivedCall(RCCallPlusSession callSession) 方法。被叫用户通过与融云服务端的连接接收来电通知。如需通过离线推送接收来电通知,App 必须已集成第三方厂商推送,详见推送 2.0 集成概述

调用接听方法与挂断方法后,SDK 内部会以异步方式执行。在主叫与被叫端触发以下回调:

通话接通后,需要设置远端用户视频渲染视图。您可以参考以下示例实现 setRemoteUserVideoView 方法,调用 CallPlus SDK 的 setVideoView 方法,传入 RCCallPlusRemoteVideoView 列表,设置远端用户视频流的渲染视图。

/**
* 设置远端用户视频渲染视图
*/
private void setRemoteUserVideoView(List<RCCallPlusUser> remoteUserList) {
List<RCCallPlusRemoteVideoView> remoteVideoViewList = new ArrayList<>();
for (RCCallPlusUser callPlusUser : remoteUserList) {
RCCallPlusRemoteVideoView remoteVideoView = new RCCallPlusRemoteVideoView(callPlusUser.getUserId(), this.getApplicationContext(), false);
//视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小
remoteVideoView.setRenderMode(RCCallPlusRenderMode.FIT);
remoteVideoViewList.add(remoteVideoView);
//本示例代码中,因为远端视图显示在最顶层,为了防止远端视频视图被底部控件(视图)遮挡,所以添加如下设置:
remoteVideoView.setZOrderOnTop(true);
remoteVideoView.setZOrderMediaOverlay(true);

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER_HORIZONTAL;
//todo 将每个远端视图(remoteVideoView)添加到XML中显示,远端为多人时,需要添加给多个控件显示,本示例代码仅展示一个远端用户情况
mRemoteVideoViewFrameLayout.removeAllViews();
mRemoteVideoViewFrameLayout.addView(remoteVideoView, params);
}

/**
* 设置远端用户视频流渲染视图给SDK
* 若没有为远端用户设置视频渲染视图,则不会产生该用户的视频流的下行流量
*/
RCCallPlusClient.getInstance().setVideoView(remoteVideoViewList);
}

发起多人通话

CallPlus for Android SDK 提供了支持多人呼叫的通话类型 RCCallPlusType.MULTI。发起多人通话与一对一通话与一对一通话流程相似,但通话类型必须指定为 RCCallPlusGroupType。多人通话一旦发起成功,融云即开始计时计费。

下文仅描述了发起多人通话的方法。在实际项目中,我们建议您先按照一对一通话 实现完整的通话流程,再按照多人通话补充实现与一对一通话有差异的步骤。

在一对一通话过程中可以邀请用户加入通话。一旦邀请成功,通话类型会自动转为多人通话。详见多人通话

步骤 11 拨打多人通话

您可以通过调用 startCall 方法发起多人通话。此方法会以异步方式执行,通话结果可在 IRCCallPlusResultListeneronStartCall 回调函数中获取。需要注意的是,多人通话和单人通话在 startCall 方法中仅体现为不同的 RCCallPlusType 类型。

List<String> userIds = new ArrayList<>();
userIds.add(remoteUserId);//todo remoteUserId 为被呼叫的远端用户userId。多人通话可以添加多个用户
RCCallPlusType callType = RCCallPlusType.MULTI;//PRIVATE: 单人通话,MULTI:多人通话
RCCallPlusMediaType mediaType = RCCallPlusMediaType.VIDEO;
RCCallPlusPushConfig pushConfig = RCCallPlusPushConfig.Builder
.create()
.build();

RCCallPlusClient.getInstance().startCall(userIds, callType, mediaType,pushConfig,"extra");

注意

有关在您的应用程序中构建语音和视频通话功能的详细指南,请参阅完整的 一对一通话多人通话 文档。我们建议您先按照一对一通话实现完整的通话流程,再按照多人通话补充实现与一对一通话有差异的步骤。


附录

以下为上文示例中 showDialog() 方法实现,仅供参考。

private AlertDialog showDialog(Context context, String content, String positiveBtn, final DialogInterface.OnClickListener positiveListener, final String negativeBtn, final DialogInterface.OnClickListener negativeListener) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder = builder.setMessage(content);
builder.setCancelable(false);
if (!TextUtils.isEmpty(positiveBtn)) {
builder.setPositiveButton(positiveBtn, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (positiveListener != null) {
positiveListener.onClick(dialog, which);
} else {
dialog.dismiss();
}
}
});
} if (!TextUtils.isEmpty(negativeBtn)) {
builder.setNegativeButton(negativeBtn, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (negativeListener != null) {
negativeListener.onClick(dialog, which);
} else {
dialog.dismiss();
}
}
});
} return builder.show();
}