自定义相机在用户未授权的情况下，预览画面黑屏，用户点击拍照，应用闪退
==================================

#### 问题现象

*   自定义相机在用户未授权的情况下，预览画面黑屏，用户点击拍照，应用闪退。jscrash报错如下：
    
    Reason:TypeError
    Error name:TypeError
    Error message:Cannot read property capture of undefined
    
*   申请相机相关资源代码：
    
    export async function cameraShooting(cameraPosition: number, surfaceId: string, context: Context, ratio: boolean):
      Promise<number\[\]\> {
      currentContext \= context;
      releaseCamera();
      let cameraManager: camera.CameraManager \= camera.getCameraManager(context);
     _// ..._ 
      let cameraArray: camera.CameraDevice\[\] \= cameraManager.getSupportedCameras();
      _// ..._ 
      cameraInput \= cameraManager.createCameraInput(cameraArray\[cameraPosition\]);
      await cameraInput.open();
      let cameraOutputCap: camera.CameraOutputCapability \=
        cameraManager.getSupportedOutputCapability(cameraArray\[cameraPosition\], camera.SceneMode.NORMAL\_PHOTO);
     _// ..._ 
      let previewProfilesArray: camera.Profile\[\] \= cameraOutputCap.previewProfiles;
      let photoProfilesArray: camera.Profile\[\] \= cameraOutputCap.photoProfiles;
      previewOutput \= cameraManager.createPreviewOutput(previewProfile, surfaceId);
     _// ..._ 
      photoOutPut \= cameraManager.createPhotoOutput(photoProfile);
     _// ..._ 
      setPhotoOutputCb(photoOutPut);
      photoSession \= cameraManager.createSession(camera.SceneMode.NORMAL\_PHOTO) as camera.PhotoSession;
      _// ..._ 
      photoSession.beginConfig();
      photoSession.addInput(cameraInput);
      photoSession.addOutput(previewOutput);
      photoSession.addOutput(photoOutPut);
      photoSession.setColorSpace(colorSpaceManager.ColorSpace.DISPLAY\_P3);
      await photoSession.commitConfig();
      await photoSession.start();
    }
    
*   相机拍照相关代码参考如下：
    
    export function capture(isFront: boolean): void {
      let settings: camera.PhotoCaptureSetting \= {
        quality: camera.QualityLevel.QUALITY\_LEVEL\_HIGH,
        rotation: camera.ImageRotation.ROTATION\_0,
        mirror: isFront
      };
      photoOutPut.capture(settings);
    }
    

#### 背景知识

*   [相机管理](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-overview)通过调用Camera Kit(相机服务)提供的接口可以开发相机应用，应用通过访问和操作相机硬件，实现基础操作，如预览、拍照和录像；还可以通过接口组合完成更多操作，如控制闪光灯和曝光时间、对焦或调焦等。
*   [相机权限](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-preparation)需要先申请相机相关权限，确保应用拥有访问相机硬件及其他功能的权限。

#### 问题定位

1.  通过jscrash日志分析为camera.PhotoOutput没有capture属性。
2.  通过createCameraInput创建输入流为空，使用try-catch抛出错误Error: not allowed, because have no permission。

#### 分析结论

1.  由于没有相机权限，无法创建相机输入流导致最终无法申请相机资源，执行createCameraInput会报错无法继续执行后续代码，最终导致photoOutPut拍照输出流为空。
2.  在拍照函数中没有进行判空，导致photoOutPut拍照输出流类为空时错误调用，最终引起jscrash问题。

#### 修改建议

1.  在初始化相机时检查相机权限是否已授予，已授予才可以申请相机权限，并且申请相机资源时如果遇到异常抛出异常，详细代码可参考官网示例代码[自定义相机定时拍摄](https://developer.huawei.com/consumer/cn/doc/architecture-guides/capture_timer-0000002352218316)中index.ets文件的aboutToAppear和onPageShow函数中检查相机权限处理过程。
2.  在拍照时应进行判空保护防止异常发生，详细代码可以参考官网示例代码[自定义相机定时拍摄](https://developer.huawei.com/consumer/cn/doc/architecture-guides/capture_timer-0000002352218316)中CameraUtils.ets文件中的capture函数对变量photoOutPut进行判空。

#### 总结

1.  在申请相机资源时必须确保应用获取相机权限，否则相机在创建输入流时会异常，无法执行后续申请资源操作。
2.  jscrash发生情况可以通过日志查看，其中一种情况为类为空时，调用类中属性会直接导致应用崩溃，在使用过程中一定要进行类判空保护。