HarmonyOS鸿蒙Next相机的基本使用实战

HarmonyOS鸿蒙Next相机的基本使用实战 相机开发流程

11.jpg

相机权限申请

"reqPermissions": [
  {
    "name": "ohos.permission.CAMERA"
  },
  {
    "name": "ohos.permission.WRITE_MEDIA"
  },
  {
    "name": "ohos.permission.MICROPHONE"
  },
  {
    "name": "ohos.permission.MEDIA_LOCATION"
  }
]

MainAbility

@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<String> 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;
        }
    }
}

相机设备创建

布局文件上添加按钮:

<Button
    ohos:id="$+id:create_camera_btn"
    ohos:height="match_content"
    ohos:width="300vp"
    ohos:text="创建相机并配置"
    ohos:text_size="20fp"
    ohos:text_color="#ffffff"
    ohos:background_element="#0000ff"
    ohos:layout_alignment="horizontal_center"
    ohos:top_padding="8vp"
    ohos:bottom_padding="8vp"
    ohos:left_padding="40vp"
    ohos:right_padding="40vp"
    ohos:top_margin="20vp"/>

按钮的逻辑代码:

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)回调,然后才可以执行相机帧捕获相关的操作。

相机配置,布局文件上加一个布局:

<DirectionalLayout
    ohos:id="$+id:surface_container"
    ohos:height="400vp"
    ohos:width="match_parent"/>

逻辑代码:

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)方法实现循环帧捕获实现预览:

//在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)方法实现预览帧配置的更新;

改变相机焦距配置

<Button
    ohos:id="$+id:change_camera_config_btn"
    ohos:height="match_content"
    ohos:width="300vp"
    ohos:text="改变相机焦距配置"
    ohos:text_size="20fp"
    ohos:text_color="#ffffff"
    ohos:background_element="#0000ff"
    ohos:layout_alignment="horizontal_center"
    ohos:top_padding="8vp"
    ohos:bottom_padding="8vp"
    ohos:left_padding="40vp"
    ohos:right_padding="40vp"
    ohos:top_margin="20vp"/>
//改变相机焦距配置
private void changeCameraConfigBtnFunc(Component component) {
    // 预览帧变焦值变更
    frameConfigBuilder.setZoom(1.5f);
    // 调用triggerLoopingCapture方法实现预览帧配置更新
    cameraDevice.triggerLoopingCapture(frameConfigBuilder.build());
}

通过stopLoopingCapture()方法停止循环帧捕获(停止预览)。

<Button
    ohos:id="$+id:stop_camera_preview_btn"
    ohos:height="match_content"
    ohos:width="300vp"
    ohos:text="停止相机预览"
    ohos:text_size="20fp"
    ohos:text_color="#ffffff"
    ohos:background_element="#0000ff"
    ohos:layout_alignment="horizontal_center"
    ohos:top_padding="8vp"
    ohos:bottom_padding="8vp"
    ohos:left_padding="40vp"
    ohos:right_padding="40vp"
    ohos:top_margin="20vp"/>
//停止相机预览
private void stopCameraBtnFunc(Component component) {
    // 停止预览帧捕获
    cameraDevice.stopLoopingCapture();
}

到这里相机的基本用户流程,基本搞清楚,使用相机最后一步就是释放了。

<Button
    ohos:id="$+id:release_camera_btn"
    ohos:height="match_content"
    ohos:width="300vp"
    ohos:text="释放相机"
    ohos:text_size="20fp"
    ohos:text_color="#ffffff"
    ohos:background_element="#0000ff"
    ohos:layout_alignment="horizontal_center"
    ohos:top_padding="8vp"
    ohos:bottom_padding="8vp"
    ohos:left_padding="40vp"
    ohos:right_padding="40vp"
    ohos:top_margin="20vp"/>
private void releaseCameraBtnFunc(Component component) {
    if (cameraDevice != null) {
        // 关闭相机和释放资源
        cameraDevice.release();
        cameraDevice = null;
    }
    // 预览配置模板置空
    previewFrameConfig = null;
}

最后的效果:

222.jpg

4 回复

哦豁,我也来感谢楼主

更多关于HarmonyOS鸿蒙Next相机的基本使用实战的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


感谢老师分享

谢楼主分享

在HarmonyOS鸿蒙Next中,相机的基本使用步骤如下:

  1. 打开相机应用:在主屏幕或应用列表中找到并点击相机图标。

  2. 选择拍摄模式:在相机界面中,滑动或点击模式选择器,选择拍照、录像、人像、夜景等模式。

  3. 调整设置:点击设置图标,调整分辨率、闪光灯、定时器等参数。

  4. 对焦与拍摄:轻触屏幕选择对焦点,点击快门按钮进行拍摄。

  5. 查看照片:拍摄后,点击右下角的缩略图可立即查看照片。

  6. 编辑与分享:在相册中,选择照片进行编辑,并通过分享按钮发送给好友或上传至社交平台。

通过这些步骤,您可以轻松使用鸿蒙Next相机进行拍摄和管理照片。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!