



dependencies {// TRTC 精简版 SDK, 包含 TRTC 和直播播放两项功能implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'// 添加 IM SDK,推荐填写最新的版本号implementation 'com.tencent.imsdk:imsdk-plus:Version number'// 如果您需要添加 Quic 插件,请取消下一行的注释(注意:要求插件版本号和 IM SDK 版本号相同)// implementation 'com.tencent.imsdk:timquic-plugin:Version number'}
defaultConfig {ndk {abiFilters "armeabi-v7a", "arm64-v8a"}}
<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.RECORD_AUDIO" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.CAMERA" /><uses-feature android:name="android.hardware.camera.autofocus" />
android:hardwareAccelerated="false",关闭硬件加速之后,会导致对方的视频流无法渲染。targetSdkVersion 为 31 或者目标设备涉及到 Android 12 及更高系统版本,官方要求需要在代码中动态申请 android.permission.BLUETOOTH_CONNECT 权限,以正常使用蓝牙功能,具体信息请参见 蓝牙权限。-keep class com.tencent.** { *; }

// 添加事件监听器V2TIMManager.getInstance().addIMSDKListener(imSdkListener);// 初始化 IM SDK,调用这个接口后,可以立即调用登录接口V2TIMManager.getInstance().initSDK(context, sdkAppID, null);// SDK 初始化后会抛出一些事件,例如连接状态、登录票据过期等private V2TIMSDKListener imSdkListener = new V2TIMSDKListener() {@Overridepublic void onConnecting() {Log.d(TAG, "IM SDK 正在连接到腾讯云服务器");}@Overridepublic void onConnectSuccess() {Log.d(TAG, "IM SDK 已经成功连接到腾讯云服务器");}};// 移除事件监听器V2TIMManager.getInstance().removeIMSDKListener(imSdkListener);// 反初始化 IM SDKV2TIMManager.getInstance().unInitSDK();
// 创建 TRTC SDK 实例(单例模式)TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);// 添加 TRTC 事件监听器mTRTCCloud.addListener(trtcSdkListener);// 来自 SDK 的各类事件通知(比如:错误码,警告码,音视频状态参数等)private TRTCCloudListener trtcSdkListener = new TRTCCloudListener() {@Overridepublic void onError(int errCode, String errMsg, Bundle extraInfo) {Log.d(TAG, errCode + errMsg);}@Overridepublic void onWarning(int warningCode, String warningMsg, Bundle extraInfo) {Log.d(TAG, warningCode + warningMsg);}};// 移除 TRTC 事件监听器mTRTCCloud.removeListener(trtcSdkListener);// 销毁 TRTC SDK 实例(单例模式)TRTCCloud.destroySharedInstance();
// 登录:userID 可自定义,userSig 参考步骤一生成获取V2TIMManager.getInstance().login(userID, userSig, new V2TIMCallback() {@Overridepublic void onSuccess() {Log.i("imsdk", "success");}@Overridepublic void onError(int code, String desc) {// 如果返回以下错误码,表示使用 UserSig 已过期,请您使用新签发的 UserSig 进行再次登录。// 1. ERR_USER_SIG_EXPIRED(6206)// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)// 注意:其他的错误码,请不要在这里调用登录接口,避免 IM SDK 登录进入死循环。Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// 登出V2TIMManager.getInstance().logout(new V2TIMCallback() {@Overridepublic void onSuccess() {Log.i("imsdk", "success");}@Overridepublic void onError(int code, String desc) {Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// 设置视频编码参数,决定远端用户看到的画面质量TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;encParam.videoFps = 15;encParam.videoBitrate = 850;encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;mTRTCCloud.setVideoEncoderParam(encParam);// 开启本地摄像头预览(可指定使用前置/后置摄像头进行视频采集)mTRTCCloud.startLocalPreview(isFrontCamera, previewView);
// 构造自定义数据JSONObject jsonObject = new JSONObject();try {jsonObject.put("cmd", "av_call");JSONObject msgJsonObject = new JSONObject();msgJsonObject.put("callType", "videoCall"); // 指定通话类型(视频通话、语音通话)msgJsonObject.put("roomId", generateRoomId()); // 指定 TRTC 房间号(主叫端可随机生成)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}String data = jsonObject.toString();// 发送呼叫邀请信令V2TIMManager.getSignalingManager().invite(receiver, data, false, v2TIMOfflinePushInfo, timeout, new V2TIMCallback() {@Overridepublic void onError(int code, String desc) {// 发送呼叫邀请信令失败// 提示呼叫失败,可以尝试重试}@Overridepublic void onSuccess() {// 发送呼叫邀请信令成功// 渲染呼叫页面,播放呼叫铃声}});
v2TIMOfflinePushInfo,详情参见 离线推送消息。timeout,单位为秒,SDK 会进行超时检测,从而实现呼叫超时自动挂断。// 被叫用户收到呼叫请求, inviteID 为该条请求 ID,inviter 为主叫用户 IDV2TIMManager.getSignalingManager().addSignalingListener(new V2TIMSignalingListener() {@Overridepublic void onReceiveNewInvitation(String inviteID, String inviter,String groupId, List<String> inviteeList, String data) {if (!data.isEmpty()) {try {JSONObject jsonObject = new JSONObject(data);String command = jsonObject.getString("cmd");JSONObject messageJsonObject = jsonObject.getJSONObject("msg");if (command.equals("av_call")) {String callType = messageJsonObject.getString("callType");String roomId = messageJsonObject.getString("roomId");// 渲染呼叫页面,播放呼叫铃声}} catch (JSONException e) {e.printStackTrace();}}}});
if (callType.equals("videoCall")) {// 设置视频编码参数,决定远端用户看到的画面质量TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;encParam.videoFps = 15;encParam.videoBitrate = 850;encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;mTRTCCloud.setVideoEncoderParam(encParam);// 开启本地摄像头预览(可指定使用前置/后置摄像头进行视频采集)mTRTCCloud.startLocalPreview(isFrontCamera, previewView);}
V2TIMManager.getSignalingManager().cancel(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { // 取消呼叫请求失败// 提示取消失败,可以尝试重试 } @Override public void onSuccess() { // 取消呼叫请求成功// 销毁呼叫页面,停止播放呼叫铃声 } });
@Override public void onInvitationCancelled(String inviteID, String inviter, String data) {// 销毁呼叫页面,停止播放呼叫铃声 }
@Overridepublic void onInvitationTimeout(String inviteID, List<String> inviteeList) {// 提示呼叫超时,销毁呼叫页面,停止播放呼叫铃声}
V2TIMManager.getSignalingManager().accept(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { // 接听失败,提示异常或重试 } @Override public void onSuccess() { // 接听成功,渲染通话页面,停止播放呼叫铃声if (callType.equals("videoCall")) {// 开始视频通话startVideoCall();} else {// 开始语音通话startAudioCall();} } });
@Overridepublic void onInviteeAccepted(String inviteID, String invitee, String data) {if (callType.equals("videoCall")) {// 开始视频通话startVideoCall();} else {// 开始语音通话startAudioCall();}}
private void startAudioCall() {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams(); params.sdkAppId = SDKAPPID; // TRTC应用标识, 在控制台获取 params.userSig = USERSIG; // TRTC鉴权凭证, 在服务端生成params.strRoomId = roomId; // 房间号, 以字符串房间号为例 params.userId = userId; // 用户名, 建议和IM保持同步mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_AUDIOCALL);}
TRTC_APP_SCENE_AUDIOCALL,同时不要指定进房角色 TRTCRoleType。startLocalAudio 可同时设置音质参数,语音通话模式建议设置 TRTC_AUDIO_QUALITY_SPEECH。// 标记是否正在通话中boolean isOnCalling = false;// 进房结果事件回调@Overridepublic void onEnterRoom(long result) {if (result > 0) {// 进房成功,标识正在通话中isOnCalling = true;} else {// 进房失败,提示通话异常isOnCalling = false;}}
private void startVideoCall() {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();params.sdkAppId = SDKAPPID; // TRTC应用标识, 在控制台获取params.userSig = USERSIG; // TRTC鉴权凭证, 在服务端生成params.strRoomId = roomId; // 房间号, 以字符串房间号为例params.userId = userId; // 用户名, 建议和IM保持同步mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);}
TRTC_APP_SCENE_VIDEOCALL,同时不要指定进房角色 TRTCRoleType。startLocalAudio 可同时设置音质参数,视频通话模式建议设置 TRTC_AUDIO_QUALITY_SPEECH。startRemoteView 拉取远端视频流渲染播放。// 标记是否正在通话中boolean isOnCalling = false;// 进房结果事件回调@Overridepublic void onEnterRoom(long result) {if (result > 0) {// 进房成功,标识正在通话中isOnCalling = true;} else {// 进房失败,提示通话异常isOnCalling = false;}}// 拉取远端视频流@Overridepublic void onUserVideoAvailable(String userId, boolean available) {// 远端用户发布/取消了主路视频画面if (available) {// 订阅远端用户的视频流,并绑定视频渲染控件mTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, view);} else {// 停止订阅远端用户的视频流,并释放渲染控件mTRTCCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);}}
private void rejectInvite(String inviteId, String data, final V2TIMCallback callback) { V2TIMManager.getSignalingManager().reject(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { if (callback != null) { callback.onError(code, desc); } } @Override public void onSuccess() { if (callback != null) { callback.onSuccess(); } } }); }JSONObject jsonObject = new JSONObject();try {jsonObject.put("cmd", "av_call");JSONObject msgJsonObject = new JSONObject();msgJsonObject.put("callType", "videoCall"); // 指定通话类型(视频通话、语音通话)msgJsonObject.put("reason", "active"); // 指定拒接类型(主动拒接、忙线拒接)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}rejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() { @Override public void onError(int code, String desc) { // 拒接失败,提示异常或重试 } @Override public void onSuccess() { // 拒接成功,销毁呼叫页面,停止播放呼叫铃声 } });
@Override public void onInviteeRejected(String inviteID, String invitee, String data) {if (!data.isEmpty()) {try {JSONObject jsonObject = new JSONObject(data);String command = jsonObject.getString("cmd");JSONObject messageJsonObject = jsonObject.getJSONObject("msg");if (command.equals("av_call")) {String reason = messageJsonObject.getString("reason");if (reason.equals("active")) {// 提示对方拒绝接听} else if (reason.equals("busy")) {// 提示对方忙线中}// 销毁呼叫页面,停止播放呼叫铃声}} catch (JSONException e) {e.printStackTrace();}}}
@Overridepublic void onReceiveNewInvitation(String inviteID, String inviter,String groupId, List<String> inviteeList, String data) {if (!data.isEmpty()) {try {JSONObject jsonObject = new JSONObject(data);String command = jsonObject.getString("cmd");JSONObject messageJsonObject = jsonObject.getJSONObject("msg");if (command.equals("av_call") && isOnCalling) {JSONObject jsonObject = new JSONObject();try {jsonObject.put("cmd", "av_call");JSONObject msgJsonObject = new JSONObject();msgJsonObject.put("callType", "videoCall"); // 指定通话类型(视频通话、语音通话)msgJsonObject.put("reason", "busy"); // 指定拒接类型(主动拒接、忙线拒接)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}// 本地正在通话中,发送忙线拒接信令rejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() {@Overridepublic void onError(int code, String desc) {// 忙线拒接失败}@Overridepublic void onSuccess() {// 忙线拒接成功}});}} catch (JSONException e) {e.printStackTrace();}}}
private void hangup() {mTRTCCloud.stopLocalAudio();mTRTCCloud.stopLocalPreview();mTRTCCloud.exitRoom();}@Overridepublic void onExitRoom(int reason) {// 已成功退出房间并挂断通话isOnCalling = false;}
@Overridepublic void onRemoteUserLeaveRoom(String userId, int reason) {hangup();}@Overridepublic void onExitRoom(int reason) {// 已成功退出房间并挂断通话isOnCalling = false;}
// 打开麦克风mTRTCCloud.muteLocalAudio(false);// 关闭麦克风mTRTCCloud.muteLocalAudio(true);
// 打开扬声器mTRTCCloud.muteAllRemoteAudio(false);// 关闭扬声器mTRTCCloud.muteAllRemoteAudio(true);
// 打开摄像头, 指定前置或后置摄像头及渲染控件mTRTCCloud.startLocalPreview(isFrontCamera, videoView);// 关闭摄像头mTRTCCloud.stopLocalPreview();
// 切换听筒mTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece);// 切换免提mTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone);
// 判断当前是否为前置摄像头boolean isFrontCamera = mTRTCCloud.getDeviceManager().isFrontCamera();// 切换前置或后置摄像头, true: 切换为前置; false: 切换为后置mTRTCCloud.getDeviceManager().switchCamera(!isFrontCamera);
@Overridepublic void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality) {if (remoteQuality.size() > 0) {switch (remoteQuality.get(0).quality) {case TRTCCloudDef.TRTC_QUALITY_Excellent:Log.i(TAG, "对方网络非常好");break;case TRTCCloudDef.TRTC_QUALITY_Good:Log.i(TAG, "对方网络比较好");break;case TRTCCloudDef.TRTC_QUALITY_Poor:Log.i(TAG, "对方网络一般");break;case TRTCCloudDef.TRTC_QUALITY_Bad:Log.i(TAG, "对方网络较差");break;case TRTCCloudDef.TRTC_QUALITY_Vbad:Log.i(TAG, "对方网络很差");break;case TRTCCloudDef.TRTC_QUALITY_Down:Log.i(TAG, "对方网络极差");break;default:Log.i(TAG, "未定义");break;}}}
localQuality 代表本地用户网络质量评估结果,其 userId 字段为空。remoteQuality 代表远端用户网络质量评估结果,其结果受远端和本地共同影响。// 开始通话时间long callStartTime = 0;// 结束通话时间long callFinishTime = 0;// 通话持续时长(秒)long callDuration = 0;// 远端用户进房回调@Overridepublic void onRemoteUserEnterRoom(String userId) {callStartTime = System.currentTimeMillis();}// 本地用户退房回调@Overridepublic void onExitRoom(int reason) {callFinishTime = System.currentTimeMillis();callDuration = (callFinishTime - callStartTime) / 1000;}
XmagicResParser.setResPath(new File(getFilesDir(), "xmagic").getAbsolutePath());//loading//copy资源文件到私有目录,只需要做一次XmagicResParser.copyRes(getApplicationContext());
XmagicResParser.setResPath(下载的资源文件本地路径);
mTRTCCloud.setLocalVideoProcessListener(TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D, TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE, new TRTCCloudListener.TRTCVideoFrameListener() {@Overridepublic void onGLContextCreated() {// SDK 内部 OpenGL 环境已经创建,此时可进行第三方美颜的初始化工作if (mXmagicApi == null) {XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());} else {mXmagicApi.onResume();}}@Overridepublic int onProcessVideoFrame(TRTCCloudDef.TRTCVideoFrame srcFrame, TRTCCloudDef.TRTCVideoFrame dstFrame) {// 用于对接第三方美颜组件的视频处理回调if (mXmagicApi != null) {dstFrame.texture.textureId = mXmagicApi.process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height);}return 0;}@Overridepublic void onGLContextDestory() {// SDK 内部 OpenGL 环境被销毁,此时可进行第三方美颜的资源销毁工作mXmagicApi.onDestroy();}});
TXCloudVideoView 作为视频渲染控件,支持 SurfaceView 和 TextureView 两种渲染方案。下面介绍指定渲染控件类型,以及更新视频渲染控件的方法。TXCloudVideoView,您可以按照如下方法进行编码。// 强制使用TextureViewTextureView textureView = findViewById(R.id.texture_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(context);cloudVideoView.addVideoView(textureView);// 强制使用SurfaceViewSurfaceView surfaceView = findViewById(R.id.surface_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(surfaceView);
// 更新本地预览画面渲染控件mTRTCCloud.updateLocalView(videoView);// 更新远端用户视频渲染控件mTRTCCloud.updateRemoteView(userId, streamType, videoView);
videoView 为 TXCloudVideoView 类型的目标视频渲染控件,streamType 仅支持 TRTC_VIDEO_STREAM_TYPE_BIG 和 TRTC_VIDEO_STREAM_TYPE_SUB。JSONObject contentObj = new JSONObject();try {contentObj.put("cmd", "av_call");JSONObject contentDetailObj = new JSONObject();contentDetailObj.put("callType", "videoCall");contentDetailObj.put("roomId", generateRoomId());contentObj.put("cmdInfo", contentDetailObj);} catch (JSONException e) {e.printStackTrace();}String data = contentObj.toString();// OfflineMessageContainerBean 是 TUIKitDemo 的透传参数 ext 对应的 JavabeanOfflineMessageContainerBean containerBean = new OfflineMessageContainerBean(); OfflineMessageBean entity = new OfflineMessageBean();entity.content = data; entity.sender = TUILogin.getLoginUser();entity.action = OfflineMessageBean.REDIRECT_ACTION_CALL; entity.sendTime = System.currentTimeMillis() / 1000; entity.nickname = mNickname; entity.faceUrl = mFaceUrl; containerBean.entity = entity; V2TIMOfflinePushInfo v2TIMOfflinePushInfo = new V2TIMOfflinePushInfo(); v2TIMOfflinePushInfo.setExt(new Gson().toJson(containerBean).getBytes()); // OPPO 必须设置 ChannelID 才可以收到推送消息,这个 ChannelID 需要和控制台一致 v2TIMOfflinePushInfo.setAndroidOPPOChannelID("tuikit");v2TIMOfflinePushInfo.setAndroidHuaWeiCategory("IM");v2TIMOfflinePushInfo.setAndroidVIVOCategory("IM");v2TIMOfflinePushInfo.setTitle(mNickname); v2TIMOfflinePushInfo.setDesc("You have a new call invitation"); // 设置自定义铃声 v2TIMOfflinePushInfo.setIOSSound("phone_ringing.mp3");v2TIMOfflinePushInfo.setAndroidSound("phone_ringing");V2TIMManager.getSignalingManager().invite(receiver, data, false, v2TIMOfflinePushInfo, timeout, new V2TIMCallback() {@Overridepublic void onError(int code, String desc) {// 发送呼叫邀请失败}@Overridepublic void onSuccess() {// 发送呼叫邀请成功}});
private void handleOfflinePush() {// 根据登录状态,判断是否需要重新登录 IM// 1. 如果登录状态为 V2TIMManager.V2TIM_STATUS_LOGOUT,跳转到登录界面,重新登录 IMif (V2TIMManager.getInstance().getLoginStatus() == V2TIMManager.V2TIM_STATUS_LOGOUT) {Intent intent = new Intent(MainActivity.this, SplashActivity.class);if (getIntent() != null) {intent.putExtras(getIntent());}startActivity(intent);finish();return;}// 2. 否则,说明 App 只是处于退后台的状态,直接解析离线推送参数final OfflineMessageBean bean = OfflineMessageDispatcher.parseOfflineMessage(getIntent());if (bean != null) {setIntent(null);NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);if (manager != null) {manager.cancelAll();}if (bean.action == OfflineMessageBean.REDIRECT_ACTION_CALL) {Intent startActivityIntent = new Intent(context, MyCustomActivity.class);startActivityIntent.putExtras(getIntent());startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(startActivityIntent);}}}
枚举 | 取值 | 描述 |
ERR_TRTC_INVALID_USER_SIG | -3320 | 进房参数 userSig 不正确,请检查 TRTCParams.userSig 是否为空。 |
ERR_TRTC_USER_SIG_CHECK_FAILED | -100018 | UserSig 校验失败,请检查参数 TRTCParams.userSig 是否填写正确或已经过期。 |
枚举 | 取值 | 描述 |
ERR_TRTC_CONNECT_SERVER_TIMEOUT | -3308 | 请求进房超时,请检查是否断网或者是否开启 VPN,您也可以切换4G进行测试。 |
ERR_TRTC_INVALID_SDK_APPID | -3317 | 进房参数 sdkAppId 错误,请检查 TRTCParams.sdkAppId 是否为空 |
ERR_TRTC_INVALID_ROOM_ID | -3318 | 进房参数 roomId 错误,请检查 TRTCParams.roomId 或 TRTCParams.strRoomId 是否为空,注意 roomId 和 strRoomId 不可混用。 |
ERR_TRTC_INVALID_USER_ID | -3319 | 进房参数 userId 不正确,请检查 TRTCParams.userId 是否为空。 |
ERR_TRTC_ENTER_ROOM_REFUSED | -3340 | 进房请求被拒绝,请检查是否连续调用 enterRoom 进入相同 Id 的房间。 |
枚举 | 取值 | 描述 |
ERR_CAMERA_START_FAIL | -1301 | 打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序。 |
ERR_MIC_START_FAIL | -1302 | 打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序。 |
ERR_CAMERA_NOT_AUTHORIZED | -1314 | 摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。 |
ERR_MIC_NOT_AUTHORIZED | -1317 | 麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。 |
ERR_CAMERA_OCCUPY | -1316 | 摄像头正在被占用中,可尝试打开其他摄像头。 |
ERR_MIC_OCCUPY | -1319 | 麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败。 |
文档反馈