客户端实现
更新时间: 2024/08/02 11:33:26
本文介绍互联网问诊的客户端实现方法,包括实现图文消息、实现音视频通话等。
前提条件
请确保您已完成以下操作:
开发环境
开发环境要求如下:
环境要求 | 说明 |
---|---|
JDK 版本 | 1.8.0 及以上版本 |
Android API 版本 | API 21、Android Studio 5.0 及以上版本 |
CPU架构 | ARM 64、ARMV7 |
IDE | Android Studio |
其他 | 依赖 Androidx,不支持 support 库。 |
技术原理
音视频通话的时序图如下图所示。
实现图文消息
互联网问诊场景方案的图文消息基于 IM UIKit 实现,更多详细功能请参见集成会话消息和 集成会话列表。
步骤1:导入 IM UIKit 组件
在您的项目的 build.gradle
中,以添加依赖的形式添加相应的 IM UIKit 组件和第三方库(Glide、Retrofit 和 OkHttp)。
groovydependencies {
// 会话列表功能组件
implementation("com.netease.yunxin.kit.conversation:conversationkit-ui:${LATEST_VERSION}")
// 聊天功能组件
implementation("com.netease.yunxin.kit.chat:chatkit-ui:${LATEST_VERSION}")
//图片库
implementation("com.netease.yunxin.kit.common:common-image:1.1.6")
//网络库
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.9.3")
}
步骤2:初始化 IM UIKit
在互联网问诊 Demo 项目的 MedicalApplication
的 initIm
文件中添加如下代码,初始化 IM UIKit。
SDKOptions options = NimSDKOptionConfig.getSDKOptions(this, “your app key”);
LoginInfo info = new LoginInfo("account","token"); // account 和 token 请替换为 IM 的 accid 和 Token
IMKitClient.init(this, info, options);
if (IMKitUtils.isMainProcess(this)) {
ChatKitClient.init(this);
}
更多初始化说明,请参见IM UIKit 的初始化。
步骤3:搭建会话列表和会话消息界面
-
在您应用中需要添加会话列表界面的 Activity 下创建
conversationFragment
。java
ConversationFragment conversationFragment = new ConversationFragment();
-
将
conversationFragment
添加到这个 Activity 中。java
FragmentManager fragmentManager = getSupportFragmentManager(); //R.id.container 你添加界面的GroupLayout fragmentManager .beginTransaction().add(R.id.container, conversationFragment) .commit();
上述示例代码中的
getSupportFragmentManager
方法属于 Android Activity 的默认方法,如果您使用 Android X 中的AppCompatActivity
则可以直接调用该方法。如果您使用的是android.app.acitivity
,则需要调用getFragmentManager
方法。
实现呼叫和音视频通话
互联网问诊场景方案的呼叫能力基于云信呼叫组件,具体请参见呼叫组件文档。
步骤1 集成呼叫组件 SDK
互联网问诊场景方案的呼叫能力基于云信呼叫组件来进行实现,请参考语音融合呼叫中的示例代码,引入呼叫组件和配置权限。
步骤2 初始化呼叫组件
IM 登录成功后,初始化呼叫组件。
示例代码
在IM登录成功之后,初始化呼叫组件
if (ProcessUtils.isMainProcess()){
initCallKit();
}
private void initCallKit() {
CallKitUIOptions options = new CallKitUIOptions.Builder()
// 必要:音视频通话 sdk appKey,用于通话中使用
.rtcAppKey(AppConstants.APP_KEY)
// 必要:当前用户 AccId
.currentUserAccId(UserInfoManager.getSelfImAccid())
// 此处为 收到来电时展示的 notification 相关配置,如图标,提示语等。
.notificationConfigFetcher(invitedInfo -> new CallKitNotificationConfig(R.mipmap.ic_launcher))
// 收到被叫时若 app 在后台,在恢复到前台时是否自动唤起被叫页面,默认为 true
.resumeBGInvitation(true)
.rtcTokenService(new TokenService() {
@Override
public void getToken(long uid, RequestCallback<String> callback) {
HttpService.requestRtcToken(uid).subscribe(new ResourceSingleObserver<BaseResponse>() {
@Override
public void onSuccess(BaseResponse response) {
LogUtil.d("getToken", "response:" + response);
if (response.isSuccessful()) {
callback.onSuccess((String) response.data);
} else {
callback.onFailed(response.code);
}
}
@Override
public void onError(Throwable e) {
LogUtil.e("getToken", "e:" + e);
callback.onException(e);
}
});
}
}) // 自己实现的 token 请求方法
.rtcSdkOption(new NERtcOption())
// 呼叫组件初始化 rtc 范围,true-全局初始化,false-每次通话进行初始化以及销毁
// 全局初始化有助于更快进入首帧页面,当结合其他组件使用时存在rtc初始化冲突可设置false
.rtcInitScope(true)
// 配置音频呼叫页
.p2pAudioActivity(CallActivity.class)
//配置视频呼叫页
.p2pVideoActivity(CallActivity.class)
.build();
// 若重复初始化会销毁之前的初始化实例,重新初始化
PstnCallKitOptions pstnCallKitOptions = new PstnCallKitOptions.Builder(options)
.timeOutMillisecond(CallConfig.CALL_TOTAL_WAIT_TIMEOUT)
.transOutMillisecond(CallConfig.CALL_PSTN_WAIT_MILLISECONDS).build();
PstnUIHelper.init(getApplicationContext(), pstnCallKitOptions);
}
步骤3 实现呼叫功能
呼叫相关代码请参考 Demo 中CallActivity
和CallViewModel
,以下是核心功能的代码示例。
// 唤起呼叫页面
CallParam param = CallParam.createSingleCallParam(ChannelType.VIDEO.getValue(), UserInfoManager.getSelfImAccid(), userModel.imAccid, extraInfo.toString());
CallKitUI.startSingleCall(context, param);
//开始呼叫
doCall(new JoinChannelCallBack() {
@Override
public void onJoinChannel(ChannelFullInfo channelFullInfo) {
LogUtil.i(TAG, "rtcCall onJoinChannel");
callback.onSuccess(channelFullInfo);
}
@Override
public void onJoinFail(String msg, int code) {
LogUtil.e(TAG, "rtcCall,onJoinFail msg:" + msg + ",code:" + code);
callback.onError(code, msg);
}
});
步骤4 实现挂断功能
示例代码
doHangup(new RequestCallbackWrapper<Void>() {
@Override
public void onResult(int code, Void result, Throwable exception) {
LogUtil.i(TAG, "rtcHangup,code:" + code + ",exception:" + exception);
callback.onSuccess(code);
}
});
步骤5 实现接听功能
示例代码
doAccept(new JoinChannelCallBack() {
@Override
public void onJoinChannel(ChannelFullInfo channelFullInfo) {
LogUtil.i(TAG, "rtcAccept onJoinChannel");
}
@Override
public void onJoinFail(String msg, int code) {
LogUtil.e(TAG, "rtcAccept,onJoinFail msg:" + msg + ",code:" + code);
}
});
步骤6 添加呼叫监听
示例代码
private final NERtcCallDelegate neRtcCallDelegate = new NERtcCallDelegate() {
@Override
public void onFirstVideoFrameDecoded(@Nullable String userId, int width, int height) {
super.onFirstVideoFrameDecoded(userId, width, height);
// 视频首帧回调
}
@Override
public void onVideoMuted(String userId, boolean isMuted) {
super.onVideoMuted(userId, isMuted);
// 对端视频mute的回调
}
@Override
public void onUserEnter(@Nullable String userId) {
super.onUserEnter(userId);
LogUtil.i(TAG, "onUserEnter,userId:" + userId);
// 用户进入通话回调
}
@Override
public void onCallEnd(@Nullable String userId) {
super.onCallEnd(userId);
LogUtil.i(TAG, "onCallEnd,userId:" + userId);
// 通话结束回调
}
@Override
public void onRejectByUserId(@Nullable String userId) {
super.onRejectByUserId(userId);
LogUtil.i(TAG, "onRejectByUserId,userId:" + userId);
// 拒绝通话的回调
}
@Override
public void onUserBusy(@Nullable String userId) {
super.onUserBusy(userId);
LogUtil.i(TAG, "onUserBusy,userId:" + userId);
// 对方占线的回调
}
@Override
public void onCancelByUserId(@Nullable String userId) {
super.onCancelByUserId(userId);
LogUtil.i(TAG, "onCancelByUserId,userId:" + userId);
// 对方取消呼叫的回调
}
@Override
public void timeOut() {
LogUtil.i(TAG, "timeOut");
// 呼叫超时的回调
}
};
NERTCVideoCall.sharedInstance().addDelegate(neRtcCallDelegate);
步骤7 移除呼叫监听
示例代码
NERTCVideoCall.sharedInstance().removeDelegate(neRtcCallDelegate);
实现虚拟背景
虚拟背景可以虚化用户周围的真实环境,或者以指定颜色的图片或自定义图像替代真实背景,可以更好的保护医生和患者的隐私。
虚拟背景的详细功能介绍和实现步骤请参见音视频通话 2.0 的虚拟背景。
//以设置虚拟背景为自定义本地图片为例
// step 1: 初始化背景
private NERtcVirtualBackgroundSource virtualBackgroundSource = new NERtcVirtualBackgroundSource();
mVirtualBackgroundSource.backgroundSourceType = NERtcVirtualBackgroundSource.BACKGROUND_IMG; //设置虚拟背景类型
mVirtualBackgroundSource.source = virtualBgImgPath; //设置背景图片路径
// step2: 开启虚拟背景
NERtcEx.getInstance().enableVirtualBackground(true, virtualBackgroundSource);
// step3: 关闭虚拟背景
NERtcEx.getInstance().enableVirtualBackground(false, null);
实现实名认证
Demo 中的实名认证页面仅供展示参考,您需要自行实现相关的业务逻辑。
实名认证的实现方法请参见网易易盾的实人认证接口,详细的解决方案介绍请参见身份信息认证解决方案。