实现1对1呼叫(含UI集成-V3)

更新时间: 2025/02/14 10:14:02

呼叫组件(NERTCCallkit)通过 UI 组件化的方式,简化了呼叫流程,您只需要调用几行代码,就可以实现 1 对 1 呼叫,即点对点呼叫,并包含呼叫的 UI 界面。本文介绍呼叫组件 V3 版本 的集成和实现方法。

V3 版本 是指呼叫组件的 V3.x.x 版本。

注意事项

  • V3 版本 的呼叫组件(NERTCCallkit)基于网易云信 NIM SDK(V10)和 NERTC SDK 实现通话呼叫,呼叫组件中已集成 NERTC SDK,V10.xx 系列的 NIM SDK 需要用户自行集成。
  • 呼叫组件默认使用 RTC 调试模式。应用正式上线前,请在 网易云信控制台 中将指定应用的 RTC 鉴权方式改回安全模式。安全模式下需要使用 Token 加入房间,详细说明请参考 Token 鉴权
  • 针对呼叫组件中的回调信息,开发者要做好相应回调数据的上报及存储,以便于后期上线之后排查问题。

基本概念

  • account_id:account_id 是 IM 账号 ID,用于登录 IM。注册 IM 账号时,IM 服务器会返回对应的账号 ID(account_id)和密钥(token),应用客户端需要负责保存 account_id 和 IM token 的映射关系。
  • Token:呼叫组件中涉及的 Token 包括 IM Token 和 RTC Token。两者不是同一个 Token,请根据实际使用场景填入对应的 Token。
    • IM Token:用于登录 IM 时进行 IM 账号鉴权。应用服务器调用 IM 服务器的 注册账号 API,获取的 IM Token。
    • RTC Token:用于加入 RTC 房间时进行 RTC 账号鉴权。应用服务器调用 NERTC 服务器的 getToken,获取的 RTC Token。

开发环境

环境要求 说明
Android Studio 版本 Android Studio 5.0 及以上版本。 Android Studio 版本编号系统的变更请参考 Android Studio 版本说明
Android API 版本 Level 为 21 及以上版本。
Android SDK 版本 Android SDK 31、Android SDK Platform-Tools 31.x.x 及以上版本。
Gradle 及所需的依赖库 Gradle Services 页面下载对应版本的 Gradle 及所需的依赖库。
  • Gradle 版本:7.4.1
  • Android Gradle 插件版本: 7.1.3
    关于 Android Gradle 插件、Gradle、SDK Tool 之间的版本依赖关系,请参考 Android Gradle 插件版本说明
kotlin 1.6.21 及以上版本。
CPU 架构 ARM 64、ARMV7。
IDE Android Studio。
其他 依赖 Androidx,不支持 support 库。
Android 系统 5.0 及以上版本的真机。由于模拟器缺少摄像头及麦克风能力,因此工程需要在真机运行。

准备工作

根据本文操作前,请确保您已经完成了以下设置:

示例项目源码

网易云信提供 1 对 1 视频通话示例项目源码,您可以基于该源码进行修改适配。

集成呼叫组件

V3 版本 呼叫组件(NERTCCallkit)基于网易云信 NIM SDK(V10)和 NERTC SDK 实现通话呼叫,呼叫组件中已集成 NERTC SDK,您只需集成 V10 版本 的 NIM SDK 即可。

第一步:集成 NIM SDK

单击查看集成 NIM SDK 的操作步骤。如果您的项目中已经集成了 NIM SDK,请忽略该步骤。
  1. 若您需要创建新项目,在 Android Studio 里,在顶部菜单依次选择 File > New > New Project 新建工程,再依次选择 Phone and Tablet > Empty Activity,单击 Next

    image

    创建 Android 项目 成功后,Android Studio 会自动开始同步 gradle, 您需要等同步成功后再进行下一步操作。

  2. 在项目根目录下的 build.gradle 文件中,配置 repositories(使用 maven)。示例代码如下:

    Groovyallprojects {
        repositories {
            mavenCentral()
        }
    }
    
  3. app 目录下的 build.gradle 文件中,配置支持的 SO 库架构。示例代码如下:

    Groovyandroid {
    defaultConfig {
        ndk {
            //设置支持的 SO 库架构
            abiFilters "armeabi-v7a", "x86","arm64-v8a","x86_64"
            }
    }
    }
    
  4. 根据开发者项目的需求,添加对应的依赖。

    NIM SDK 组件版本号 必须一致。可在 SDK 更新日志 中查看当前最新版本。

    Groovydependencies {
        compile fileTree(dir: 'libs', include: '*.jar')
        // 添加依赖。注意,版本号必须一致。
    
        // 基础功能 (必需)
        implementation "com.netease.nimlib:basesdk:${LATEST_VERSION}"
    
        // 聊天室需要
        implementation "com.netease.nimlib:chatroom:${LATEST_VERSION}"
    
        // 通过网易云信来集成小米等厂商推送需要
        implementation "com.netease.nimlib:push:${LATEST_VERSION}"
    
        // 超大群需要
        implementation "com.netease.nimlib:superteam:${LATEST_VERSION}"
    
        // 全文检索插件
        implementation "com.netease.nimlib:lucene:${LATEST_VERSION}"
    }
    
  5. 添加权限。

    根据实际应用需求,在 AndroidManifest.xml 中添加以下配置,并请将 com.netease.nim.demo 替换为自己的包名。

    XML<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.netease.nim.demo">
    
        <!-- 权限声明 -->
        <!-- 访问网络状态-->
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    
        <!-- 外置存储存取权限 -->
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
        <!-- 多媒体相关 -->
        <uses-permission android:name="android.permission.CAMERA"/>
        <uses-permission android:name="android.permission.RECORD_AUDIO"/>
        <!-- Android11:V8.6.1 及之后的版本不需要。其他:V4.4.0 及之后的版本不需要。 -->
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    
        <!-- 控制呼吸灯,振动器等,用于新消息提醒 -->
        <uses-permission android:name="android.permission.FLASHLIGHT" />
        <uses-permission android:name="android.permission.VIBRATE" />
    
        <!-- 8.0+系统需要-->
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
        <!-- 下面的 uses-permission 一起加入到您的 AndroidManifest 文件中。-->
        <permission
            android:name="${applicationId}.permission.RECEIVE_MSG"
            android:protectionLevel="signature"/>
        <uses-permission android:name="${applicationId}.permission.RECEIVE_MSG"/>
    
        <application
            ...>
            <!-- App Key, 可以在这里设置,也可以在 SDKOptions 中提供。
                如果 SDKOptions 中提供了,则取 SDKOptions 中的值。-->
            <meta-data
                android:name="com.netease.nim.appKey"
                android:value="key_of_your_app" />
    
            <!-- 网易云信后台服务,请使用独立进程。-->
            <service
                android:name="com.netease.nimlib.service.NimService"
                android:process=":core"/>
            <!-- 网易云信后台服务,使用 V10 接口需要添加以下代码。-->
            <service
                android:name="com.netease.nimlib.service.NimServiceV2" />
    
            <!-- 网易云信后台辅助服务 -->
            <service
                android:name="com.netease.nimlib.job.NIMJobService"
                android:exported="false"
                android:permission="android.permission.BIND_JOB_SERVICE"
                android:process=":core"/>
    
            <!-- 网易云信监视系统启动和网络变化的广播接收器,保持和 NimService 同一进程 -->
            <receiver android:name="com.netease.nimlib.service.NimReceiver"
                android:process=":core"
                android:exported="false">
                <intent-filter>
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
                </intent-filter>
            </receiver>
    
            <!-- 网易云信进程间通信 Receiver -->
            <receiver android:name="com.netease.nimlib.service.ResponseReceiver"/>
    
            <!-- 网易云信进程间通信 service -->
            <service android:name="com.netease.nimlib.service.ResponseService"/>
    
            <!-- 网易云信进程间通信 provider -->
            <provider
                android:name="com.netease.nimlib.ipc.NIMContentProvider"
                android:authorities="${applicationId}.ipc.provider"
                android:exported="false"
                android:process=":core" />
            <!-- 网易云信内部使用的进程间通信 provider -->
            <!-- SDK 启动时会强制检测该组件的声明是否配置正确,如果检测到该声明不正确,SDK 会主动抛出异常引发崩溃 -->
            <provider
                android:name="com.netease.nimlib.ipc.cp.provider.PreferenceContentProvider"
                android:authorities="${applicationId}.ipc.provider.preference"
                android:exported="false" />
    
            <!-- 网易云信内部使用的进程间通信 provider -->
            <!-- SDK 启动时会强制检测该组件的声明是否配置正确,如果检测到该声明不正确,SDK 会主动抛出异常引发崩溃 -->
            <provider
                android:name="com.netease.nimlib.ipc.cp.provider.PreferenceContentProvider"
                android:authorities="com.netease.nim.demo.ipc.provider.preference"
                android:exported="false" />
        </application>
    </manifest>
    

SDK 版本限制

  • 呼叫组件与 NIM SDK、NERTC SDK 之间存在映射关系,使用呼叫组件时,必须使用指定版本的 NIM SDK 和 NERTC SDK。当前最新版本 V3.3.0 适配 NIM SDK V10.6.0 和 NERTC SDK V5.6.50,其他版本的适配关系请参考 更新日志

  • 如果您已经集成了 NIM SDK 和 NERTC SDK,或因业务需求等原因无法使用指定版本 SDK,请联系网易云信技术支持确认是否能替换 SDK 版本,并参考 Gradle 引入呼叫组件 中的步骤 3 去除呼叫组件依赖的版本。

第二步:初始化 NIM SDK

NIM SDK 支持在应用代码的任意位置初始化。

调用 NIMClient#initV2 方法进行初始化。

SDK 的配置信息请参考 SDKOptions

示例代码如下:

Java// 激活 V10 API 后,可以根据该字段选项选择是否禁用 V10 API 登录,默认 false,即使用 V10 API 登录
// sdkOptions.disableV2Login = true;
...
// 按需设置其它 SDKOptions 设置项

NIMClient.initV2(context, sdkOptions);

以上提供了一个简化的初始化示例,更多初始化信息请参考 初始化 SDK

第三步:实现登录 IM

调用 login 方法登录 IM。

本文以实现 静态 Token 登录为例,动态 Token 登录以及自动登录的实现方法请参考 登录 IM

示例代码如下:

JavaNIMClient.getService(V2NIMLoginService.class).login("account", "token", null, new V2NIMSuccessCallback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        // TODO
    }
},
    new V2NIMFailureCallback() {
    @Override
    public void onFailure(V2NIMError error) {
        int code = error.getCode();
        String desc = error.getDesc();
        // TODO
    }
});

第四步:Gradle 引入呼叫组件

  1. 在工程根部目录的 build.gradle 文件中添加如下代码。

    Groovyallprojects {
        repositories {
            //...
            mavenCentral()
            //...
        }
    }
    
  2. 在主工程 build.gradle 文件中添加如下代码,引入呼叫组件。

    Groovy// 若出现 More than one file was found with OS independent path 'lib/arm64-v8a/libc++_shared.so'.
    // 可以在主 module 的 build.gradle 文件中 android 闭包内追加如下 packageOptions 配置
    android{
        //......
        packagingOptions {
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        }
    }
    // 引入呼叫组件安装包,导入以下其中一个
    dependencies {
        implementation 'com.netease.yunxin.kit.call:call-ui:3.3.0' // 含 UI 集成时,请导入这个包
        implementation 'com.netease.yunxin.kit.call:call:3.3.0'     // 基础组件包,不含 UI 集成时请导入这个包
    
    }
    
  3. (可选)去除呼叫组件依赖的 SDK。

    如果因业务需求或其他原因无法使用指定版本 SDK,您可以参考如下步骤去除呼叫组件依赖的 IM 和 RTC 的 SDK。

    Groovyimplementation('com.netease.yunxin.kit.call:call-ui:1.8.1') {
            exclude group: 'com.netease.nimlib'// 去除组件依赖的 IM sdk
            exclude group: 'com.netease.yunxin', module: 'nertc-base' // 去除组件依赖的 NERTC sdk
    }
    
  4. 配置防代码混淆。

    代码混淆是指使用简短无意义的名称重命名类、方法、属性等,增加逆向工程的难度,保障 Android 程序源码的安全性。为了避免因重命名类,导致调用呼叫组件异常,您需要配置防代码混淆。

    请在 proguard-rules.pro 配置文件中加入以下代码防止混淆:

    # NIM SDK 的类,如果集成 IM 时已经添加,请忽略
    -dontwarn com.netease.nim.**
    -keep class com.netease.nim.** {*;}
    
    -dontwarn com.netease.nimlib.**
    -keep class com.netease.nimlib.** {*;}
    
    -dontwarn com.netease.share.**
    -keep class com.netease.share.** {*;}
    
    -dontwarn com.netease.mobsec.**
    -keep class com.netease.mobsec.** {*;}
    
    # NERTC SDK 的类
    -keep class com.netease.lava.** {*;}
    -keep class com.netease.yunxin.** {*;}
    
    # 呼叫组件的类
    -dontwarn com.netease.yunxin.kit.**
    -keep class com.netease.yunxin.kit.** {*;}
    -keep public class * extends com.netease.yunxin.kit.corekit.XKitInitOptions
    -keep class * implements com.netease.yunxin.kit.corekit.XKitService {*;}
    

第五步:初始化呼叫组件 NERTCCallkit

IM 登录成功之后,需要调用 init 接口进行呼叫组件的初始化。初始化时需要设置以下必选参数,其他参数可以按需配置。

  • rtcAppKey:网易云信应用的 AppKey,请在 网易云信控制台 中应用详情页面中查看指定应用的 AppKey。
  • currentUserAccId:当前用户的 IM account_id。

App 用户在本端完成初始化后才可以正常接收其他人的的呼叫,或主动发起呼叫。若未完成初始化,组件可能会提示应用进行初始化,或被叫方 App 在被呼叫时无提示。若 App 重复调用初始化接口,则会销毁上次初始化设置,以新的初始化设置为准。

呼叫组件初始化相关代码内容可以放在工程的 MainActivity 中执行,尽量避免在 MainActivity#onDestroy() 方法中做组件的释放。建议在 App 用户登出时释放,登入时进行初始化。

  • 初始化呼叫组件相关步骤需要在 IM 登录成功之后进行。
  • 核心功能参数说明请参考 初始化参数配置

示例代码

JavaCallKitUIOptions options = new CallKitUIOptions.Builder()
  // 必要:音视频通话 sdk appKey,用于通话中使用
  .rtcAppKey(appKey)
  // 必要:当前用户 account_id
  .currentUserAccId("currentUserAccIdFromIM")
  // 通话接听成功的超时时间单位 毫秒,默认 30s
  .timeOutMillisecond(30 * 1000L)
  // 此处为 收到来电时展示的 notification 相关配置,如图标,提示语等。
  .notificationConfigFetcher(neInviteInfo -> new CallKitNotificationConfig(R.drawable.ic_logo))
  // 收到被叫时若 app 在后台,在恢复到前台时是否自动唤起被叫页面,默认为 true
  .resumeBGInvitation(true)
  // 请求 rtc token 服务,若非安全模式则不需设置(V1.8.0 版本之前需要配置,V1.8.0 及之后版本无需配置)
  //.rtcTokenService((uid, callback) -> requestRtcToken(appKey, uid, callback)) // 自己实现的 token 请求方法
  // 设置初始化 RTC SDK 相关配置,按照所需进行配置
  .rtcSdkOption(new NERtcOption())
  // 呼叫组件初始化 rtc 范围,NECallInitRtcMode.GLOBAL-全局初始化,
  // NECallInitRtcMode.IN_NEED-每次通话进行初始化以及销毁,全局初始化有助于更快进入首帧页面,
  // 当结合其他组件使用时存在 rtc 初始化冲突可设置 NECallInitRtcMode.IN_NEED
  // 或当结合其他组件使用时存在 rtc 初始化冲突可设置 NECallInitRtcMode.IN_NEED_DELAY_TO_ACCEPT
  .initRtcMode(NECallInitRtcMode.IN_NEED)
  .build();
// 不要重复初始化组件可能会产生 sdk 初始化失败问题
CallKitUI.init(getApplicationContext(), options);

实现 1 对 1 呼叫

呼叫组件(NERTCCallkit)的典型应用场景为 1 对 1 呼叫场景,即用户 A 发起视频呼叫用户 B,用户 B 同意呼叫,通话接通、两人进行实时音视频通信。

呼叫组件 UI kit 内部已包括了呼叫的相关逻辑,您只需要调用几行代码触发呼叫即可。

1 对 1 呼叫的业务流程如下:

  1. 用户 A 以及用户 B 均完成网易云信 IM SDK 的登录,并成功初始化呼叫组件。

  2. 用户 A 获取到自己以及用户 B 登录网易云信 IM SDK 的账号(account_id)。

  3. 用户 A 通过 startSingleCall 呼叫用户 B。

    Java// @param type:呼叫类型 NECallType.AUDIO-音频呼叫,NECallType.VIDEO-视频呼叫
    // @param calledAccId:被叫方 IM 账号 account_id
    CallParam param = new CallParam.Builder()
      .callType(NECallType.VIDEO)
      .calledAccId(calledAccId)
      .build();
    CallKitUI.startSingleCall(getActivity(), param);
    
  4. 用户 B 单击被叫页面的接听按钮进行视频通话。

  5. 通话完成后单击挂断即可。

自定义 UI

您可以根据呼叫组件已有设置,自定义界面,详情请参考 自定义 UI

进阶功能

呼叫组件(NERTCCallkit)除基础呼叫流程外,还支持话单功能、自定义 UI 等,您可以参考进阶功能文档实现相关业务流程。

此文档是否对你有帮助?
有帮助
去反馈
  • 注意事项
  • 基本概念
  • 开发环境
  • 准备工作
  • 示例项目源码
  • 集成呼叫组件
  • 第一步:集成 NIM SDK
  • 第二步:初始化 NIM SDK
  • 第三步:实现登录 IM
  • 第四步:Gradle 引入呼叫组件
  • 第五步:初始化呼叫组件 NERTCCallkit
  • 实现 1 对 1 呼叫
  • 自定义 UI
  • 进阶功能