**相机开发流程**  **相机权限申请** config.json ```java "reqPermissions": [ {"name": "ohos.permission.CAMERA" }, { "name": "ohos.permission.WRITE_MEDIA"}, {"name": "ohos.permission.MICROPHONE"}, { "name": "ohos.permission.MEDIA_LOCATION"} ] ``` MainAbility ```java @Override public void onStart(Intent intent) { super.onStart(intent); super.setMainRoute(MainAbilitySlice.class.getName()); requestPermissions(); } private void requestPermissions() { String[] permissions = { SystemPermission.CAMERA, SystemPermission.MICROPHONE, SystemPermission.MEDIA_LOCATION, SystemPermission.WRITE_MEDIA }; List
permissionFiltered = Arrays.stream(permissions) .filter(permission -> verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED) .collect(Collectors.toList()); requestPermissionsFromUser(permissionFiltered.toArray(new String[permissionFiltered.size()]), 0); } @Override public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) { if (permissions == null || permissions.length == 0 || grantResults == null || grantResults.length == 0) { return; } for (int grantResult : grantResults) { if (grantResult != IBundleManager.PERMISSION_GRANTED) { terminateAbility(); break; } } } ``` **相机设备创建** 布局文件上添加按钮: ```java
``` 按钮的逻辑代码: ```java private void createCameraBtnFunc(Component component) { //openCamera(); //先测试创建相机 initSurface(); //创建surface,里面包含的openCamera() } private void openCamera(){ System.out.println("createCameraBtnFunc start..."); CameraKit cameraKit = CameraKit.getInstance(getContext()); if(cameraKit == null){ System.out.println("cameraKit create error!"); } System.out.println("cameraKit create success!"+cameraKit); try { // 获取当前设备的逻辑相机列表 String[] cameraIds = cameraKit.getCameraIds(); if (cameraIds.length <= 0) { System.out.println("cameraIds size is 0"); } System.out.println("逻辑相机ids:" + Arrays.toString(cameraIds)); //第一个参数cameraId //第二和第三个参数负责相机创建和相机运行时的数据和状态检测 cameraKit.createCamera(cameraIds[0], new CameraStateCallbackImpl(), new EventHandler(EventRunner.create("CameraCb"))); } catch (IllegalStateException e) { // 处理异常 } } private class CameraStateCallbackImpl extends CameraStateCallback { @Override public void onCreated(Camera camera) { //创建相机成功的时候回调 } @Override public void onConfigured(Camera camera) { } } ``` 至此,相机设备的创建已经完成,执行成功意味着相机系统的硬件已经完成了上电。创建相机设备成功后,在CameraStateCallback中会触发onCreated(Camera camera)回调,并且带回Camera对象,用于执行相机设备的操作。当一个新的相机设备成功创建后,首先需要对相机进行配置,调用configure(CameraConfig)方法实现配置。 **相机设备配置** 相机配置主要是设置预览、拍照、录像所需要用到的Surface(ohos.agp.graphics.Surface),没有配置过Surface,相应的功能不能使用。为了进行相机帧捕获结果的数据和状态检测,有时还需要在相机配置时调用setFrameStateCallback(FrameStateCallback, EventHandler)方法设置帧回调。相机配置成功后,在CameraStateCallback中会触发onConfigured(Camera camera)回调,然后才可以执行相机帧捕获相关的操作。 相机配置,布局文件上加一个布局: ```java
``` 逻辑代码: ```java private SurfaceProvider surfaceProvider; private DirectionalLayout surfaceContainer; //定义在最前面 private void initSurface() { getWindow().setTransparent(true); DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig( ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT); surfaceProvider = new SurfaceProvider(this); surfaceProvider.setLayoutConfig(params); surfaceProvider.pinToZTop(false); surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack()); surfaceContainer.addComponent(surfaceProvider); } private class SurfaceCallBack implements SurfaceOps.Callback { @Override public void surfaceCreated(SurfaceOps callbackSurfaceOps) { //surfaceCreated后可以创建相机对象, 按钮上点击后执行initSurface(); openCamera(); } @Override public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) { } } //在上面的CameraStateCallbackImpl的onCreated方法中添加代码 private Camera cameraDevice; private Surface previewSurface; private CameraConfig.Builder cameraConfigBuilder; //放前面 private final class CameraStateCallbackImpl extends CameraStateCallback { @Override public void onCreated(Camera camera) { //创建相机成功的时候回调 cameraDevice = camera; previewSurface = surfaceProvider.getSurfaceOps().get().getSurface(); cameraConfigBuilder = camera.getCameraConfigBuilder(); if (cameraConfigBuilder == null) { System.out.println("onCreated cameraConfigBuilder is null"); return; } // 配置预览的Surface cameraConfigBuilder.addSurface(previewSurface); // 配置帧结果的回调 cameraConfigBuilder.setFrameStateCallback(frameStateCallbackImpl, new EventHandler(EventRunner.create())); try { // 相机设备配置 camera.configure(cameraConfigBuilder.build()); } catch (IllegalArgumentException e) { System.out.println("Argument Exception"); } catch (IllegalStateException e) { System.out.println("State Exception"); } } } private FrameStateCallback frameStateCallbackImpl = new FrameStateCallback(){ //....更具需要实现接口里的方法 }; ``` 配置完成后,会回调public void onConfigured(Camera camera)方法,在这个方法里铺货相机拍摄的帧。 **相机帧捕获** 用户一般都是先看见预览画面才执行拍照或者其他功能,所以对于一个普通的相机应用,预览是必不可少的。通过getFrameConfigBuilder(FRAME_CONFIG_PREVIEW)方法获取预览配置模板,更多的帧配置项以及详细使用方法请参考API接口说明的FrameConfig.Builder部分。 **通过triggerLoopingCapture(FrameConfig)方法实现循环帧捕获实现预览:** ```java //在CameraStateCallbackImpl的onConfigured添加代码 private FrameConfig.Builder frameConfigBuilder; private FrameConfig previewFrameConfig; private final class CameraStateCallbackImpl extends CameraStateCallback { @Override public void onConfigured(Camera camera) { //配置成功的时候回调 // 获取预览配置模板 frameConfigBuilder = camera.getFrameConfigBuilder(Camera.FrameConfigType.FRAME_CONFIG_PREVIEW); // 配置预览Surface frameConfigBuilder.addSurface(previewSurface); previewFrameConfig = frameConfigBuilder.build(); try { // 启动循环帧捕获 int triggerId = camera.triggerLoopingCapture(previewFrameConfig); } catch (IllegalArgumentException e) { System.out.println("Argument Exception"); } catch (IllegalStateException e) { System.out.println("State Exception"); } } } ``` 经过以上的操作,相机应用已经可以正常进行实时预览了。在预览状态下,开发者还可以执行其他操作,比如:当预览帧配置更改时,可以通过triggerLoopingCapture(FrameConfig)方法实现预览帧配置的更新; ```java
``` ```java //改变相机焦距配置 private void changeCameraConfigBtnFunc(Component component) { // 预览帧变焦值变更 frameConfigBuilder.setZoom(1.5f); // 调用triggerLoopingCapture方法实现预览帧配置更新 cameraDevice.triggerLoopingCapture(frameConfigBuilder.build()); } ``` 通过stopLoopingCapture()方法停止循环帧捕获(停止预览)。 ```java
``` ```java //停止相机预览 private void stopCameraBtnFunc(Component component) { // 停止预览帧捕获 cameraDevice.stopLoopingCapture(); } ``` 到这里相机的基本用户流程,基本搞清楚,使用相机最后一步就是释放了。 ```java
``` ```java private void releaseCameraBtnFunc(Component component) { if (cameraDevice != null) { // 关闭相机和释放资源 cameraDevice.release(); cameraDevice = null; } // 预览配置模板置空 previewFrameConfig = null; } ``` 最后的效果:  [想了解更多关于鸿蒙的内容,请访问:](https://harmonyos.51cto.com/#bkwz) [51CTO和华为官方战略合作共建的鸿蒙技术社区](https://harmonyos.51cto.com/#bkwz) https://harmonyos.51cto.com/#bkwz