You need to enable JavaScript to run this app.
导航

设备权限处理

最近更新时间2023.10.12 15:24:40

首次发布时间2023.10.12 15:24:40

在使用 RTC 过程中,需要获取设备权限以确保实时通信体验,例如音频通信需要麦克风权限、视频通信需要摄像头权限、PC 端屏幕共享需要屏幕录制权限等。
通过阅读本文,您将获得麦克风、摄像头权限配置的最佳实践指导。

Android
  1. App 权限配置

/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"  />
  1. App 内申请麦克风、摄像头权限
//常量,用于回调
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)
iOS & macOS
  1. App 权限配置

在 App 的 Info.plist 中添加以下两项,分别对应麦克风和摄像头在系统弹出授权对话框时的提示信息。
Privacy - Microphone Usage Description,并填入麦克风使用目的提示语。
Privacy - Camera Usage Description,并填入摄像头使用目的提示语。

  1. App 内申请麦克风、摄像头权限
//检查权限状态。摄像头: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

不更改 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)

注意:设置内权限被关闭导致无法获取权限时,需在设置-隐私-麦克风/摄像头内开启权限。

Electron
  1. 创建 entitlements.mac.plist 文件,并增加如下配置:
<?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>
  1. 配置 package.json
"mac": {
      "entitlements": "build/entitlements.mac.plist",
      "extendInfo": {
        "NSMicrophoneUsageDescription": "授权访问麦克风",
        "NSCameraUsageDescription": "授权访问摄像头"
      }
    }
  1. 申请麦克风/摄像头权限
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 获取权限的相关内容。