requestCallPermissions static method

Future<CallPermissionResult> requestCallPermissions({
  1. required CallType callType,
})

音视频通话发起前的权限检查与请求。

调用时机:用户点击“发起通话”后,真正启动 RTC 引擎之前。 返回 CallPermissionResult,调用方根据 granted 决定是否继续, 根据 hasPermanentlyDenied 决定是否引导用户前往设置。

Implementation

static Future<CallPermissionResult> requestCallPermissions({
  required CallType callType,
}) async {
  // Web 端交由浏览器在 WebRTC 启动时处理,这里不拦截
  if (kIsWeb) {
    return const CallPermissionResult(
      granted: true,
      microphonePermanentlyDenied: false,
      cameraPermanentlyDenied: false,
      microphoneStatus: PermissionStatus.granted,
    );
  }

  if (kDebugMode) {
    final before = await Permission.microphone.status;
    debugPrint('[Permission] mic before request: $before');

    if (callType == CallType.video) {
      final cameraStatusBefore = await Permission.camera.status;
      debugPrint('[Permission] camera before request: $cameraStatusBefore');
    }
  }

  // iOS 首次请求前,notDetermined 会被 permission_handler 映射为 denied。
  // 因此不能“先看到 denied 就判定为永久拒绝”,必须先发起 request()。
  // 只有在 request 之后仍为 permanentlyDenied,才是真正的永久拒绝。[reference:3]
  final permissions = <Permission>[Permission.microphone];
  if (callType == CallType.video) {
    permissions.add(Permission.camera);
  }

  final statuses = await permissions.request();

  final micStatus = statuses[Permission.microphone] ?? PermissionStatus.denied;
  final camStatus = callType == CallType.video
      ? statuses[Permission.camera]
      : null;

  final micGranted = micStatus.isGranted;
  final camGranted = camStatus == null || camStatus.isGranted;

  return CallPermissionResult(
    granted: micGranted && camGranted,
    microphonePermanentlyDenied: micStatus.isPermanentlyDenied,
    cameraPermanentlyDenied: camStatus?.isPermanentlyDenied ?? false,
    microphoneStatus: micStatus,
    cameraStatus: camStatus,
  );
}