目录

如何排查相机界面黑屏问题

问题现象

应用使用相机功能时,相机页面黑屏。

背景知识

问题定位

  1. 检查应用是否有相机权限ohos.permission.CAMERA。查看日志,如果出现以下日志,说明应用缺少相机权限。

    I     [CreateBusinessError:30] CreateBusinessError errCode: 201 errMsg: Permission denied.

    说明:需要考虑用户拒绝授权后不会出现上方的日志,此时需要继续筛查日志。

    1. 检查应用中是否声明相机权限。如果出现以下日志,代表未声明相机权限:
      [IsDynamicRequest:444]Permission: ohos.permission.CAMERA: state: 2, errorReason: 2

      说明:errorReason: 2表示应用未声明该权限。详情参照PermissionRequestResult属性中errorReasons属性部分。

    2. 检查应用是否有调用requestPermissionsFromUser或requestPermissionOnSetting接口申请相机权限。
    3. 检查用户是否授权。
      • 检查是否存在以下日志,该段日志表示用户在权限弹窗中拒绝授权(reqPerms数组和result数组是对应的,result数组中-1表示拒绝授权,0表示允许授权):
        [SPC][PermissionDialog][Model]: terminate session with result, resultCode: 1, reqPerms: [ohos.permission.CAMERA], result: [-1].
      • 检查是否存在以下日志,该段日志表示调用requestPermissionsFromUser方法时,已确认应用缺少相机权限,且无法再次通过该接口拉起权限申请弹窗。
        [IsDynamicRequest:444]Permission: ohos.permission.CAMERA: state: -1, errorReason: 0
        [RequestPermissionsFromUserExecute:704]It does not need to request permission
  2. 查看相机设备是否被占用。查看日志,若出现下方日志,说明相机设备被占用。
    xxx, Camera input error code: 7400109
    Can not use camera cause of preempted
  3. 排查createPreviewOutput参数配置是否异常。若出现如下日志,说明未获取到surfaceId。
    {CreatePreviewOutputInstance():869} CameraManagerNapi::CreatePreviewOutputInstance ParseProfile size.width = xxx, size.height = xxx, format = 1003, surfaceId =
    {CreatePreviewOutput():341} CreatePreviewOutput is called
    <surface_utils.cpp:48-GetSurface>: Cannot find surface, uniqueId: 0.
    {CreatePreviewOutput():357} failed to get surface

    可能原因为初次进入页面时在onPageShow中初始化相机,而此时XComponent组件还未创建,无法获取到XComponent组件的surfaceId。

  4. 排查当前使用的摄像头,查看on('foldStatusChange')中折叠状态切换后是否重新获取当前可用的摄像头。
  5. 排查接口调用时序是否正确。查看日志,若出现下方日志,说明接口调用时序异常。
    • 添加或移除相机的输入流和输出流操作未在beginConfig和commitConfig之间会出现如下日志:
      {AddInput():666} CaptureSession::AddInput operation Not allowed!
      initCamera fail: {"code":"7400102"}
    • 未beginConfig就开始进行commitConfig操作会出现如下日志:
      {CommitConfig():424} CaptureSession::CommitConfig operation Not allowed!
      initCamera fail: {"code":"7400102","message":"Operation not allowed."}
    • 会话配置前,调用start操作会出现如下日志:
      {Start():1261} CaptureSession::Start Session not Commited
      initCamera fail: {"code":"7400103","message":"Session not config."}
  6. 查看添加的输入流/输出流是否可用。查看日志,若出现下方日志,说明添加了不可用的输入流/输出流。
    CanAddxxx check failed.
    initCamera fail: {"code":"7400201","message":"Camera service fatal error."}
  7. 排查在应用退至后台/手机设备锁屏等场景下返回相机界面后的设置,若应用未在onPageShow中重新初始化相机,相机功能无法拉起,相机界面黑屏。

分析结论

  1. 缺少相机权限。
    • 未声明相机权限。
    • 应用未向用户申请相机权限。
    • 用户未授权使用相机。
  2. 其他应用处于后台时未释放相机资源,相机对象被占用,无法获取相机设备。
  3. 折叠屏切换折叠状态后未更换当前使用的摄像头。
  4. 在XComponent创建前就创建预览流,未获取到surfaceId。
  5. 方法调用时序存在问题。
    • 添加或移除相机的输入流和输出流操作未在beginConfig和commitConfig之间。
    • 未beginConfig就开始进行commitConfig操作。
    • 会话配置前,调用start操作。
  6. 添加了不可用的输入流/输出流。
  7. 返回页面后未重新初始化相机。

修改建议

  1. 申请相机权限ohos.permission.CAMERA。
  2. 占用相机对象的应用处于后台时应释放相机资源。
  3. 折叠状态改变后,需要重新获取到当前设备折叠状态下可用的摄像头列表,并切换至可用摄像头,可参考适配不同折叠状态的摄像头变更(ArkTS)。
  4. 首次进入页面时,在XComponent创建后再创建预览流。
  5. 调整方法调用时序。
    • 添加或移除相机的输入流和输出流操作在beginConfig和commitConfig之间。
    • beginConfig操作后再进行commitConfig操作。
    • 会话配置后调用start操作。
  6. 使用canAddInput和canAddOutput判断当前输入流和输出流是否可用,将不可用输入流/输出流替换为可用的。
  7. 返回页面后重新初始化相机。

示例代码可以参考预览(ArkTS)。