dependencies {// TRTC SDK lite version, includes two features: TRTC and live streaming playbackimplementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'// Add IM SDK. It is recommended to use the latest version numberimplementation 'com.tencent.imsdk:imsdk-plus:Version number'// If you need to add Quic plugin, uncomment the next line (Note: Version number of the plugin needs to be the same as that of the 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"
. Disabling hardware acceleration will result in failure to render the other party's video stream.targetSdkVersion
is 31 or higher, or if the target device runs Android 12 or a newer version, the official requirement is to dynamically request android. permission.BLUETOOTH_CONNECT
permission in the code to use the Bluetooth feature properly. For more information, see Bluetooth Permissions.-keep class com.tencent.** { *; }
// Add event listenerV2TIMManager.getInstance().addIMSDKListener(imSdkListener);// Initialize the IM SDK. After calling this API, you can immediately call the log-in APIV2TIMManager.getInstance().initSDK(context, sdkAppID, null);// After the SDK is initialized, it will trigger various events, such as connection status and expiration of log-in credentialsprivate V2TIMSDKListener imSdkListener = new V2TIMSDKListener() {@Overridepublic void onConnecting() {Log.d(TAG, "IM SDK is connecting to the Cloud Virtual Machine");}@Overridepublic void onConnectSuccess() {Log.d(TAG, "IM SDK has successfully connected to the Cloud Virtual Machine");}};// Remove event listenerV2TIMManager.getInstance().removeIMSDKListener(imSdkListener);// Deinitialize the IM SDKV2TIMManager.getInstance().unInitSDK();
// Create TRTC SDK instance (single instance pattern)TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);// Add TRTC event listenermTRTCCloud.addListener(trtcSdkListener);// Notifications from various SDK events (e.g., error codes, warning codes, audio and video status parameters, etc.)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);}};// Remove TRTC event listenermTRTCCloud.removeListener(trtcSdkListener);// Destroy TRTC SDK instance (single instance pattern)TRTCCloud.destroySharedInstance();
// Log in: userID can be defined by the user and userSig can be generated as per step 1V2TIMManager.getInstance().login(userID, userSig, new V2TIMCallback() {@Overridepublic void onSuccess() {Log.i("imsdk", "success");}@Overridepublic void onError(int code, String desc) {// The following error codes indicate an expired userSig, and you need to generate a new one for log-in again.// 1. ERR_USER_SIG_EXPIRED(6206).// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001).// Note: Do not call the log-in API in case of other error codes. Otherwise, the IM SDK may enter an infinite loop of log-in.Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// Log outV2TIMManager.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);}});
// Set video encoding parameters to determine the picture quality seen by remote usersTRTCCloudDef.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);// Enable local camera preview (you can specify to use the front/rear camera for video capture)mTRTCCloud.startLocalPreview(isFrontCamera, previewView);
// Construct custom dataJSONObject jsonObject = new JSONObject();try {jsonObject.put("cmd", "av_call");JSONObject msgJsonObject = new JSONObject();msgJsonObject.put("callType", "videoCall"); // Specify the call type (video call, audio call)msgJsonObject.put("roomId", generateRoomId()); // Specify the TRTC room ID (caller can generate it randomly)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}String data = jsonObject.toString();// Send call invitation signalingV2TIMManager.getSignalingManager().invite(receiver, data, false, v2TIMOfflinePushInfo, timeout, new V2TIMCallback() {@Overridepublic void onError(int code, String desc) {// Failed to send call invitation signaling// Prompt call failure, you can try to retry}@Overridepublic void onSuccess() {// Successfully send call invitation signaling// Render call page, play call ringtone}});
v2TIMOfflinePushInfo
in the invitation signaling. For details, see Offline Push Message.timeout
in the invitation signaling, in seconds. The SDK will perform timeout detection to realize auto hang up after call timeout.// Callee receives the call request. The inviteID is the request ID, and inviter is the caller 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");// Render call page, play call ringtone}} catch (JSONException e) {e.printStackTrace();}}}});
if (callType.equals("videoCall")) {// Set video encoding parameters to determine the picture quality seen by remote usersTRTCCloudDef.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);// Enable local camera preview (you can specify to use the front/rear camera for video capture)mTRTCCloud.startLocalPreview(isFrontCamera, previewView);}
V2TIMManager.getSignalingManager().cancel(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) {// Failed to cancel the call request// Prompt cancel failed, you can try to retry } @Override public void onSuccess() {// Successfully cancel the call request// Terminate the call page, and stop the call ringtone }});
@Override public void onInvitationCancelled(String inviteID, String inviter, String data) {// Terminate the call page, and stop the call ringtone}
@Overridepublic void onInvitationTimeout(String inviteID, List<String> inviteeList) {// Prompt call timeout. Terminate the call page, and stop the call ringtone}
V2TIMManager.getSignalingManager().accept(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) {// Answer failed, prompt for exception or retry } @Override public void onSuccess() {// Answer successfully, render the call page, and stop the call ringtoneif (callType.equals("videoCall")) {// Start video callstartVideoCall();} else {// Start audio callstartAudioCall();} } });
@Overridepublic void onInviteeAccepted(String inviteID, String invitee, String data) {if (callType.equals("videoCall")) {// Start video callstartVideoCall();} else {// Start audio callstartAudioCall();}}
private void startAudioCall() {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams(); params.sdkAppId = SDKAPPID;// TRTC application ID, obtained from the console params.userSig = USERSIG;// TRTC authentication credential, generated on the serverparams.strRoomId = roomId; // Room ID, take the room ID string as an example params.userId = userId;// Username, it is recommended to stay sync with IMmTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_AUDIOCALL);}
TRTC_APP_SCENE_AUDIOCALL
, and the room entry role TRTCRoleType
should not be specified.startLocalAudio
allows you to set audio quality parameters at the same time. For audio calls, it is recommended to set TRTC_AUDIO_QUALITY_SPEECH
.// Mark whether the call is in progressboolean isOnCalling = false;// Event callback for the result of entering the room@Overridepublic void onEnterRoom(long result) {if (result > 0) {// Room entry successful, indicates that the call is in progressisOnCalling = true;} else {// Failed to enter the room, prompt for call exceptionisOnCalling = false;}}
private void startVideoCall() {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();params.sdkAppId = SDKAPPID;// TRTC application ID, obtained from the consoleparams.userSig = USERSIG; // TRTC authentication credential, generated on the serverparams.strRoomId = roomId; // Room ID, take the room ID string as an exampleparams.userId = userId;// Username, it is recommended to stay sync with IMmTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);}
TRTC_APP_SCENE_VIDEOCALL
, and the room entry role TRTCRoleType
should not be specified.startLocalAudio
allows you to set audio quality parameters at the same time. For video calls, it is recommended to set TRTC_AUDIO_QUALITY_SPEECH
.startRemoteView
to pull and render the remote video stream.// Mark whether the call is in progressboolean isOnCalling = false;// Event callback for the result of entering the room@Overridepublic void onEnterRoom(long result) {if (result > 0) {// Room entry successful, indicates that the call is in progressisOnCalling = true;} else {// Failed to enter the room, prompt for call exceptionisOnCalling = false;}}// Pull remote video stream@Overridepublic void onUserVideoAvailable(String userId, boolean available) {// The remote user publishes/unpublishes the primary videoif (available) {// Subscribe to the remote user's video stream and bind the video rendering controlmTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, view);} else {// Unsubscribe to the remote user's video stream and release the rendering controlmTRTCCloud.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"); // Specify the call type (video call, audio call)msgJsonObject.put("reason", "active"); // Specify rejection type (Proactive Rejection, Busy Line Rejection)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}rejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() { @Override public void onError(int code, String desc) {// Rejection failed, prompt for exception or retry } @Override public void onSuccess() {// Rejection successful. Terminate the call page, and stop the call ringtone }});
@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")) {// Prompt that the other party rejects call} else if (reason.equals("busy")) {// Prompt that the other party is busy}// Terminate the call page, and stop the call ringtone}} 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"); // Specify the call type (video call, audio call)msgJsonObject.put("reason", "busy"); // Specify rejection type (Proactive Rejection, Busy Line Rejection)jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}// Local call is in progress, and sends busy line rejection signalrejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() {@Overridepublic void onError(int code, String desc) {// Busy line rejection failed}@Overridepublic void onSuccess() {// Busy line rejection successful}});}} catch (JSONException e) {e.printStackTrace();}}}
reject
signaling for implementation, but it's important to distinguish them through the reason
field of the custom data
in the signaling.private void hangup() {mTRTCCloud.stopLocalAudio();mTRTCCloud.stopLocalPreview();mTRTCCloud.exitRoom();}@Overridepublic void onExitRoom(int reason) {// Successfully exited the room and hung up the callisOnCalling = false;}
@Overridepublic void onRemoteUserLeaveRoom(String userId, int reason) {hangup();}@Overridepublic void onExitRoom(int reason) {// Successfully exited the room and hung up the callisOnCalling = false;}
// Turn the mic onmTRTCCloud.muteLocalAudio(false);// Turn the mic offmTRTCCloud.muteLocalAudio(true);
// Turn the speaker onmTRTCCloud.muteAllRemoteAudio(false);// Turn the speaker offmTRTCCloud.muteAllRemoteAudio(true);
// Turn the camera on, specifying front or rear camera and the rendering controlmTRTCCloud.startLocalPreview(isFrontCamera, videoView);// Turn the camera offmTRTCCloud.stopLocalPreview();
// Switch to earpiecemTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece);// Switch to speakerphonemTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone);
// Determine if the current camera is front-facingboolean isFrontCamera = mTRTCCloud.getDeviceManager().isFrontCamera();// Switch between front and rear cameras, true: switch to front-facing; false: switch to rear-facingmTRTCCloud.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, "The other party's network is very good");break;case TRTCCloudDef.TRTC_QUALITY_Good:Log.i(TAG, "The other party's network is quite good");break;case TRTCCloudDef.TRTC_QUALITY_Poor:Log.i(TAG, "The other party's network is average");break;case TRTCCloudDef.TRTC_QUALITY_Bad:Log.i(TAG, "The other party's network is poor");break;case TRTCCloudDef.TRTC_QUALITY_Vbad:Log.i(TAG, "The other party's network is very poor");break;case TRTCCloudDef.TRTC_QUALITY_Down:Log.i(TAG, "The other party's network is extremely poor");break;default:Log.i(TAG, "Undefined");break;}}}
localQuality
represents the local user network quality assessment result, and its userId field is empty.remoteQuality
represents the remote user network quality assessment result, which is influenced by factors on both the remote and local sides.// Start call timelong callStartTime = 0;// End call timelong callFinishTime = 0;// Call duration (seconds)long callDuration = 0;// Callback for remote user entering room@Overridepublic void onRemoteUserEnterRoom(String userId) {callStartTime = System.currentTimeMillis();}// Callback for local user exiting room@Overridepublic void onExitRoom(int reason) {callFinishTime = System.currentTimeMillis();callDuration = (callFinishTime - callStartTime) / 1000;}
XmagicResParser.setResPath(new File(getFilesDir(), "xmagic").getAbsolutePath());//loading// Copy resource files to the private directory. Only need to do it onceXmagicResParser.copyRes(getApplicationContext());
XmagicResParser.setResPath (local path of the downloaded resource file);
mTRTCCloud.setLocalVideoProcessListener(TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D, TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE, new TRTCCloudListener.TRTCVideoFrameListener() {@Overridepublic void onGLContextCreated() {// The OpenGL environment has already been set up internally within the SDK. At this point, the initialization of third-party beauty features can be doneif (mXmagicApi == null) {XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());} else {mXmagicApi.onResume();}}@Overridepublic int onProcessVideoFrame(TRTCCloudDef.TRTCVideoFrame srcFrame, TRTCCloudDef.TRTCVideoFrame dstFrame) {// Callback for integrating with third-party beauty components for video processingif (mXmagicApi != null) {dstFrame.texture.textureId = mXmagicApi.process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height);}return 0;}@Overridepublic void onGLContextDestory() {// The internal OpenGL environment within the SDK has been terminated. At this point, proceed to clean up resources for third-party beauty featuresmXmagicApi.onDestroy();}});
TXCloudVideoView
is used as the video rendering control, and both SurfaceView
and TextureView
rendering schemes are supported. Below are the methods for specifying the type of rendering control and updating the video rendering control.TXCloudVideoView
, you can code as follows.// Mandatory use ofTextureView
TextureView textureView = findViewById(R.id.texture_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(context);cloudVideoView.addVideoView(textureView);// Mandatory use ofSurfaceView
SurfaceView surfaceView = findViewById(R.id.surface_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(surfaceView);
// Update local preview screen rendering controlmTRTCCloud.updateLocalView(videoView);// Update the remote user's video rendering controlmTRTCCloud.updateRemoteView(userId, streamType, videoView);
videoView
is a target video rendering control of type TXCloudVideoView
. streamType
only supports TRTC_VIDEO_STREAM_TYPE_BIG
and 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 is the Javabean corresponding to the pass-through parameter ext in TUIKitDemoOfflineMessageContainerBean 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());// For OPPO, it is essential to set ChannelID to receive push messages. This ChannelID needs to be consistent with that in the consolev2TIMOfflinePushInfo.setAndroidOPPOChannelID("tuikit");v2TIMOfflinePushInfo.setAndroidHuaWeiCategory("IM");v2TIMOfflinePushInfo.setAndroidVIVOCategory("IM");v2TIMOfflinePushInfo.setTitle(mNickname);v2TIMOfflinePushInfo.setDesc("You have a new call invitation");// Set a custom ringtonev2TIMOfflinePushInfo.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) {// Failed to send call invitation}@Overridepublic void onSuccess() {// Successfully send call invitation}});
private void handleOfflinePush() {// Determine whether to log in to IM again based on the log-in status// 1. If the log-in status is V2TIMManager.V2TIM_STATUS_LOGOUT, you will redirect to the log-in interface, and log in to IM againif (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. Otherwise, it means the app is just in the background, directly parse the offline push parametersfinal 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);}}}
onError
callback. For details, see Error Code Table.Enumeration | Value | Description |
ERR_TRTC_INVALID_USER_SIG | -3320 | Room entry parameter userSig is incorrect. Check if TRTCParams.userSig is empty. |
ERR_TRTC_USER_SIG_CHECK_FAILED | -100018 | UserSig verification failed. Check if the parameter TRTCParams.userSig is filled in correctly or has expired. |
Enumeration | Value | Description |
ERR_TRTC_CONNECT_SERVER_TIMEOUT | -3308 | Room entry request timed out. Check if your internet connection is lost or if a VPN is enabled. You may also attempt to switch to 4G for testing. |
ERR_TRTC_INVALID_SDK_APPID | -3317 | Room entry parameter sdkAppId is incorrect. Check if TRTCParams.sdkAppId is empty |
ERR_TRTC_INVALID_ROOM_ID | -3318 | Room entry parameter roomId is incorrect.Check if TRTCParams.roomId or TRTCParams.strRoomId is empty. Nnote that roomId and strRoomId cannot be used interchangeably. |
ERR_TRTC_INVALID_USER_ID | -3319 | Room entry parameter userId is incorrect. Check if TRTCParams.userId is empty. |
ERR_TRTC_ENTER_ROOM_REFUSED | -3340 | Room entry request was denied. Check if enterRoom is called consecutively to enter rooms with the same ID. |
Enumeration | Value | Description |
ERR_CAMERA_START_FAIL | -1301 | Failed to enable the camera. For example, if there is an exception for the camera's configuration program (driver) on a Windows or Mac device, you should try disabling then re-enabling the device, restarting the machine, or updating the configuration program. |
ERR_MIC_START_FAIL | -1302 | Failed to open the mic. For example, if there is an exception for the camera's configuration program (driver) on a Windows or Mac device, you should try disabling then re-enabling the device, restarting the machine, or updating the configuration program. |
ERR_CAMERA_NOT_AUTHORIZED | -1314 | The device of camera is unauthorized. This typically occurs on mobile devices and may be due to the user having denied the permission. |
ERR_MIC_NOT_AUTHORIZED | -1317 | The device of mic is unauthorized. This typically occurs on mobile devices and may be due to the user having denied the permission. |
ERR_CAMERA_OCCUPY | -1316 | The camera is occupied. Try a different camera. |
ERR_MIC_OCCUPY | -1319 | The mic is occupied. This occurs when, for example, the user is currently having a call on the mobile device. |
Was this page helpful?