在使用 RTC 过程中,需要获取设备权限以确保实时通信体验,例如音频通信需要麦克风权限、视频通信需要摄像头权限、PC 端屏幕共享需要屏幕录制权限等。
通过阅读本文,您将获得麦克风、摄像头权限配置的最佳实践指导。
在 /app/Manifests/AndroidManifest.xml
文件中的 </application>
标签后添加以下权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <!-- 对于 Android 12.0 及以上设备,还需要添加如下权限: --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
//常量,用于回调 int MY_PERMISSION_APPLY = 1; //要使用的摄像头权限。摄像头:CAMERA;麦克风:RECORD_AUDIO int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); //判断是否有摄像头权限 if (permission == PackageManager.PERMISSION_GRANTED) { //有权限,直接执行 } else { //没有权限,提示获取权限 String[] perms = {"android.permission.CAMERA"}; ActivityCompat.requestPermissions(this, perms, MY_PERMISSION_APPLY); } public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){ switch(permsRequestCode){ case MY_PERMISSION_APPLY: boolean accepted = grantResults[0]==PackageManager.PERMISSION_GRANTED; if(!accepted){ //用户拒绝了权限 }else{ //用户同意了权限 } break; } }
权限未获取时,会收到以下回调:
//未获取麦克风权限,错误类型为 MEDIA_DEVICE_ERROR_NOPERMISSION public void com.ss.bytertc.engine.handler.IRTCVideoEventHandler.onAudioDeviceStateChanged( String deviceID, AudioDeviceType deviceType, int deviceState, int deviceError) //未获取摄像头权限,错误类型为 MEDIA_DEVICE_ERROR_NOPERMISSION public void com.ss.bytertc.engine.handler.IRTCVideoEventHandler.onVideoDeviceStateChanged( String deviceID, VideoDeviceType deviceType, int deviceState, int deviceError)
在 App 的 Info.plist 中添加以下两项,分别对应麦克风和摄像头在系统弹出授权对话框时的提示信息。
Privacy - Microphone Usage Description,并填入麦克风使用目的提示语。
Privacy - Camera Usage Description,并填入摄像头使用目的提示语。
//检查权限状态。摄像头:AVMediaTypeVideo;麦克风:AVMediaTypeAudio AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; //权限定义 typedef NS_ENUM(NSInteger, AVAuthorizationStatus) { AVAuthorizationStatusNotDetermined = 0, /* 尚未询问是否开启麦克风*/ AVAuthorizationStatusRestricted = 1, /* 未授权,家长限制*/ AVAuthorizationStatusDenied = 2, /* 用户未授权*/ AVAuthorizationStatusAuthorized = 3, /* 用户授权*/ } API_AVAILABLE(macos(10.14), ios(7.0)) __WATCHOS_PROHIBITED __TVOS_PROHIBITED; //申请权限 if (authStatus == AVAuthorizationStatusNotDetermined) { [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { dispatch_async(dispatch_get_main_queue(), ^{ if (granted) { [self doSomething]; } else { [self showAlertWithTitle:@"温馨提示" message:@"您没有开启\"麦克风\"权限\n 无法进行通话。请在设置中开启麦克风权限。"]; } }); }]; } else if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted) { [self showAlertWithTitle:@"温馨提示" message:@"您没有开启\"麦克风\"权限\n 无法进行通话。\n 请在设置中开启麦克风权限。"]; } else if (authStatus == AVAuthorizationStatusAuthorized) { [self doSomething]; }
权限未获取时,会收到以下回调:
//未获取麦克风权限,错误类型为 ByteRTCMediaDeviceErrorDeviceNoPermission - (void)rtcEngine:(ByteRTCVideo * _Nonnull)engine onAudioDeviceStateChanged:(NSString*_Nonnull)deviceID device_type:(ByteRTCAudioDeviceType)deviceType device_state:(ByteRTCMediaDeviceState)deviceState device_error:(ByteRTCMediaDeviceError)deviceError; //未获取摄像头权限,错误类型为 ByteRTCMediaDeviceErrorDeviceNoPermission - (void)rtcEngine:(ByteRTCVideo * _Nonnull)engine onVideoDeviceStateChanged:(NSString*_Nonnull)deviceID device_type:(ByteRTCVideoDeviceType)deviceType device_state:(ByteRTCMediaDeviceState)deviceState device_error:(ByteRTCMediaDeviceError)deviceError;
注意:如果 iOS 未开启后台模式,进入后台后音视频通话会中断。开启后即可保持后台音视频通话。
不更改 Windows 系统设置前提下,麦克风/摄像头权限无需申请即可直接访问。
如果在系统设置界面关闭麦克风/摄像头权限,会收到以下回调:
//未获取麦克风权限,错误类型为 kMediaDeviceErrorDeviceNoPermission virtual void bytertc::IRTCVideoEventHandler::onAudioDeviceStateChanged( const char* device_id, bytertc::RTCAudioDeviceType device_type, bytertc::MediaDeviceState device_state, bytertc::MediaDeviceError device_error) //未获取摄像头权限,错误类型为 kMediaDeviceErrorDeviceNoPermission virtual void bytertc::IRTCVideoEventHandler::onVideoDeviceStateChanged( const char* device_id, bytertc::RTCVideoDeviceType device_type, bytertc::MediaDeviceState device_state, bytertc::MediaDeviceError device_error)
注意:设置内权限被关闭导致无法获取权限时,需在设置-隐私-麦克风/摄像头内开启权限。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.cs.allow-jit</key> <true/> <key>com.apple.security.cs.allow-unsigned-executable-memory</key> <true/> <key>com.apple.security.cs.allow-dyld-environment-variables</key> <true/> <key>com.apple.security.device.audio-input</key> <true/> <key>com.apple.security.device.camera</key> <true/> </dict> </plist>
"mac": { "entitlements": "build/entitlements.mac.plist", "extendInfo": { "NSMicrophoneUsageDescription": "授权访问麦克风", "NSCameraUsageDescription": "授权访问摄像头" } }
const { ipcMain,systemPreferences } = require('electron') //获取麦克风权限 ipcMain.on("getMediaAccessStatus",async ()=>{ //检测麦克风权限是否开启 let getMediaAccessStatus = systemPreferences.getMediaAccessStatus('microphone') if(getMediaAccessStatus !== 'granted'){ //请求麦克风权限 if (process.platform === "darwin") { await systemPreferences.askForMediaAccess("microphone"); } } }) //获取摄像头权限 ipcMain.on("getMediaAccessStatus",async ()=>{ //检测摄像头权限是否开启 let getMediaAccessStatus = systemPreferences.getMediaAccessStatus('camera') if(getMediaAccessStatus !== 'granted'){ //请求摄像头权限 if (process.platform === "darwin") { await systemPreferences.askForMediaAccess("camera"); } } }) //可以通过以下方法确认屏幕录制权限的状态 const screenPrivilege = systemPreferences.getMediaAccessStatus("screen");
注意:在 macOS 12.1 以上系统中,调试运行时正常,但打包成安装包后安装并启动时出现崩溃的问题。为解决这一问题,需要在主进程内主动申请麦克风/摄像头权限,具体参考上文 Electron 获取权限的相关内容。