客户端实现
本文介绍如何使用声网灵隼纯呼叫版本的客户端示例项目在 Android 客户端实现呼叫和通话等功能。
纯呼叫版本的客户端示例项目提供呼叫、实时音视频等功能。你需要自行实现账号管理和设备管理相关逻辑。
如果你已有自研的设备管理等模块,声网建议你使用纯呼叫版本示例项目。
前提条件
开始前,请确保你的开发环境满足以下条件:
- Android Studio 4.1.2 或以上版本。
- Android API level 16 或以上。
- 运行 Android 4.1 或以上版本的移动设备。
- 参考开通并配置声网灵隼物联网服务开通灵隼服务。
业务流程
在纯呼叫模式下,你需要自行实现账号系统与设备管理功能。基本流程如下:
跑通示例项目
运行步骤
-
从 GitHub 上下载最新版本的 Android 客户端示例项目。
-
使用 Android Studio 加载工程后,在 app>>res>>values>>config.xml 文件中,将以下配置项修改为你在灵隼控制台的应用配置>>开发者选项页面中获取的相关参数。详见开通声网灵隼服务。
-
连接上 Android 设备后,用 Android Studio 编译并运行示例项目。
-
直接输入要登录的账号名称。
-
登录成功后,会显示当前账号信息。
- 当前账号显示的是实际账号名称。
- 账号 ID 是账号的唯一标识。
- 对端账号 ID 可以输出要主动呼叫的对端账号 ID。
如果要呼叫的对端是一个设备,你可以根据设备的 (Product Key + Device ID) 计算出设备的账号 ID。
(可选)开通离线呼叫
当 Android 端应用不再运行时(包括不在后台运行时或应用进程不存在时),离线呼叫可以实现在有设备端呼叫客户端时,客户端能收到后台服务,并启动应用来接听设备端呼叫。你可以参考以下步骤开通离线呼叫:
-
在
app\src\main\res\values\config.xml
文件中配置离线呼叫的相应参数。XML<!-- 声网灵隼控制台的应用配置>>开发者选项中的 Easemob App Key -->
<string name="EASEMOB_APPKEY">your_easemob_appkey</string>
<!-- 配置 FCM 离线推送参数 -->
<bool name="FCM_ENBALE">false</bool>
<string name="FCM_SENDERID"></string>
<!-- 配置小米手机离线推送参数 -->
<string name="MI_PUSH_APPID"></string>
<string name="MI_PUSH_APPKEY"></string>
<!-- 配置 OPPO 手机离线推送参数 -->
<string name="OPPO_PUSH_APPKEY"></string>
<string name="OPPO_PUSH_APPSECRET"></string>
<!-- 配置 VIVIO 手机离线推送参数 -->
<integer name="VIVO_PUSH_APPID">0</integer>
<string name="VIVO_PUSH_APPKEY"></string>
<!-- 配置华为手机离线推送参数,注意‘appid=’不要删除 -->
<string name="HUAWEI_PUSH_APPKID">appid=106736987</string> -
恢复
\app\src\main\AndroidManifest.xml
文件中关于离线推送注释的代码。主要包括离线推送权限配置、离线推送账号配置和离线推送服务配置。 -
恢复
app\build.gradle
中标注为各手机厂商离线推送 SDK
的代码 ,以集成各家手机厂商的离线推送 SDK。gradle// // 各手机厂商离线推送SDK
// //implementation(name: 'oppo_push_v2.1.0', ext: 'aar')
// implementation 'com.huawei.hms:push:4.0.2.300'
// implementation files('libs/mi_push_v3.6.12.jar')
// implementation files('libs/vivo_push_v2.3.1.jar')
// implementation 'io.hyphenate:hyphenate-push:0.1.0' // 环信
//
// // Google firebase 离线推送
// implementation 'com.google.android.gms:play-services-base:18.1.0'
// implementation 'com.google.firebase:firebase-messaging:23.0.6' -
\app\src\main\io\agora\iotlinkdemo\base\PushApplication.java
文件的PushApplication.onCreate()
方法中,恢复 import 语句和标注为初始化环信的离线推送
的代码。Java//import io.agora.iotlinkdemo.huanxin.EmAgent;
//
// 初始化环信的离线推送
//
// if (mMetaData != null)
// {
// EmAgent.EmPushParam pushParam = new EmAgent.EmPushParam();
// pushParam.mFcmSenderId = mMetaData.getString("com.fcm.push.senderid", "");
// pushParam.mMiAppId = mMetaData.getString("com.mi.push.app_id", "");
// pushParam.mMiAppKey = mMetaData.getString("com.mi.push.api_key", "");
// pushParam.mOppoAppKey = mMetaData.getString("com.oppo.push.api_key", "");
// pushParam.mOppoAppSecret = mMetaData.getString("com.oppo.push.app_secret", "");;
// pushParam.mVivoAppId = String.valueOf(mMetaData.getInt("com.vivo.push.app_id", 0));
// pushParam.mVivoAppKey = mMetaData.getString("com.vivo.push.api_key", "");
// pushParam.mHuaweiAppId = mMetaData.getString("com.huawei.hms.client.appid", "");
// EmAgent.getInstance().initialize(this, pushParam);
// }
} -
在
\app\src\main\io\agora\iotlinkdemo\base\PushApplication.java
文件的PushApplication.initializeEngine()
方法中,恢复以下代码:JavainitParam.mPusherId = EmAgent.getInstance().getEid();
-
在
\app\src\main\io\agora\iotlinkdemo\huanxin\EmAgent.java
文件,恢复全部代码。
对于华为推送,你还要进行以下额外步骤:
-
恢复以下文件中的全部代码:
\app\src\main\io\agora\iotlinkdemo\huanxin\HMSPushHelper.java
\app\src\main\io\agora\iotlinkdemo\huanxin\HMSPushService.java
-
从AppGallery Connect下载
agconnect-services.json
文件,覆盖\app\agconnect-services.json
文件。 -
将证书文件
iot.jks
的 SHA256 指纹,填写到AppGallery Connect中。
客户端实现
Android 客户端的核心逻辑如下。
配置离线推送账号信息
在你的 Android 项目中,修改 AndroidManifest.xml
文件配置离线推送账号信息。参考开通声网灵隼服务获取账号信息。
初始化
参考以下步骤调用 initialize()
方法来初始化。参考开通声网灵隼服务获取相关参数。
登录用户账号
你不需要进行账号注册,直接输入用户账号名字进行无密码登录。
// 使用账号进行登录
int ret = AIotAppSdkFactory.getInstance().getAccountMgr().login(accountName, password);
// 登录成功/失败后,触发 IAccoungMgr.ICallback.onLoginDone() 回调
@Override
public void onLoginDone(int errCode, String account) { }
登录成功后,本机可以开始进行呼叫、接听和挂断操作。
String localAccountId = ACallkitSdkFactory.getInstance().getAccountMgr().getAccountId();
客户端呼叫设备端
-
客户端发出呼叫请求。
Java// 通过对端账号 ID 来呼叫对端,可以同时附带一些呼叫消息
int ret = ACallkitSdkFactory.getInstance().getCallkitMgr().callDial(peerAccountId, attachMsg);
// 呼叫完成后,触发 ICallkitMgr.ICallback.onDialDone()回调事件
// 可以根据 errCode 错误码判断呼叫是否成功,或者对端是否忙
@Override
public void onDialDone(int errCode, final String peerAccountId) { } -
客户端发出呼叫请求成功后,设备端会有三种状态回应:
- 设备端正常接听,客户端接收到
ICallkitMgr.ICallback.onPeerAnswer(IotDevice iotDev)
回调事件,进入双方通话状态。 - 设备端拒绝接听,客户端接收到
ICallkitMgr.ICallback.onPeerHangup(IotDevice iotDev)
回调事件,结束本次通话。 - 设备端超时不回应,客户端接收到
ICallkitMgr.ICallback.onPeerTimer(IotDevice iotDev)
回调事件,结束本次通话。
如果呼叫的对端是一个设备,并且知道设备的 productKey 和 deviceId,可以按照固定规则来生成对端设备的 accountId。
具体规则如下:
Java// 根据设备的 (productKey + deviceId) 生成相应的 accountId
String peerName = productKey + "-" + deviceId;
String base32Name = Base32.encodeAsString(peerName.getBytes());
String devAccountId = base32Name.replace("=", ""); - 设备端正常接听,客户端接收到
-
正常接通时,客户端会接收到
ICallkitMgr.ICallback.onPeerFirstVideo(IotDevice iotDevice, int videoWidth, int videoHeight)
事件,表示接收到设备端首帧视频帧,应用层可以根据自己实际的显示业务逻辑进行处理。正常通话过程中,客户端可以发送音视频,对端也可以发送音视频。客户端可以调用AIotAppSdkFactory.getInstance().getCallkitMgr().setAudioEffect();
来设置各种变声效果。客户端也可以设置设备端是否推送音视频流等达到静音等效果,详见ICallkitMgr
接口提供的方法。 -
如果客户端想要结束通话,调用
AIotAppSdkFactory.getInstance().getCallkitMgr().callHangup();
方法主动挂断电话。在通话过程中接收到ICallkitMgr.ICallback.onPeerHangup(IotDevice iotDev)
事件,说明对端设备主动挂断,结束通话。
设备端呼叫客户端
-
客户端处于空闲状态时,如果有设备端呼叫,会接收到来电呼叫事件
ICallkitMgr.ICallback.onPeerIncoming()
,你可以根据自己的业务逻辑显示来电界面。Java// 来自于设备端的呼叫,附带消息
@Override
public void onPeerIncoming(IotDevice iotDevice, String attachMsg) -
客户端根据实际的业务逻辑进行处理。
- 如果客户端正常接听,则调用
ICallkitMgr.getCallkitMgr. callAnswer(IotDevice iotDev)
方法,进入双方通话状态。 - 如果客户端拒绝接听,则调用
ICallkitMgr.getCallkitMgr.callHangup(IotDevice iotDev)
方法挂断 ,结束本次通话。 - 如果客户端不回应,设备端会超时主动挂断,客户端接收到
ICallkitMgr.ICallback. onPeerHangup(String peerAccount)
回调事件,结束本次通话。
- 如果客户端正常接听,则调用
-
正常接通时,客户端会接收到
ICallkitMgr.ICallback.onPeerFirstVideo(IotDevice iotDevice, int videoWidth, int videoHeight)
事件,表示接收到设备端首帧视频帧,应用层可以根据自己实际的显示业务逻辑进行处理。正常通话过程中,客户端可以发送音视频,对端也可以发送音视频。客户端可以调用ACallkitSdkFactory.getInstance().getCallkitMgr().setAudioEffect();
来设置各种变声效果。客户端也可以设置设备端是否推送音视频流等达到静音等效果,详见ICallkitMgr
接口提供的方法。 -
如果客户端想要结束通话,调用
ACallkitSdkFactory.getInstance().getCallkitMgr().callHangup();
方法主动挂断电话。在通话过程中接收到ICallkitMgr.ICallback. onPeerHangup(String peerAccount)
事件,说明对端设备主动挂断,结束通话。
参考信息
你可以通过客户端 Android API 参考(纯呼叫)了解 API 的详细信息。