客户端实现

更新时间: 2023/06/29 09:30:35

本文介绍互联网问诊的客户端实现方法,包括实现图文消息、实现音视频通话等。

前提条件

请确保您已完成以下操作:

开发环境

开发环境要求如下:

环境要求 说明
JDK 版本 1.8.0 及以上版本
Android API 版本 API 21、Android Studio 5.0 及以上版本
CPU架构 ARM 64、ARMV7
IDE Android Studio
其他 依赖 Androidx,不支持 support 库。

技术原理

音视频通话的时序图如下图所示。

uml diagram

实现图文消息

互联网问诊场景方案的图文消息基于 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 项目的 MedicalApplicationinitIm 文件中添加如下代码,初始化 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:搭建会话列表和会话消息界面

图文消息.png

  1. 在您应用中需要添加会话列表界面的 Activity 下创建conversationFragment

    javaConversationFragment conversationFragment = new ConversationFragment();
    
  2. 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方法。

实现呼叫和音视频通话

互联网问诊场景方案的呼叫能力基于云信呼叫组件,具体请参见呼叫组件文档

视频呼叫.png

步骤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 中CallActivityCallViewModel,以下是核心功能的代码示例。

   // 唤起呼叫页面 
   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 中的实名认证页面仅供展示参考,您需要自行实现相关的业务逻辑。

实名认证的实现方法请参见网易易盾的实人认证接口,详细的解决方案介绍请参见身份信息认证解决方案

此文档是否对你有帮助?
有帮助
去反馈
  • 前提条件
  • 开发环境
  • 技术原理
  • 实现图文消息
  • 步骤1:导入 IM UIKit 组件
  • 步骤2:初始化 IM UIKit
  • 步骤3:搭建会话列表和会话消息界面
  • 实现呼叫和音视频通话
  • 步骤1 集成呼叫组件 SDK
  • 步骤2 初始化呼叫组件
  • 步骤3 实现呼叫功能
  • 步骤4 实现挂断功能
  • 步骤5 实现接听功能
  • 步骤6 添加呼叫监听
  • 步骤7 移除呼叫监听
  • 实现虚拟背景
  • 实现实名认证