Android Camera2 教程 · 第二章 · 开关相机

Android Camera2 教程 · 第二章 · 开关相机上一章 Camera2 概览 里我们介绍了一些 Camera2 的基础知识 但是并没有涉及太多的 API 从本章开始我们会开发一个具有完整相机功能的应用程序 并且将相机知识分成多个篇章进行介绍 而本章所要介绍的就是相机的开启流程 阅读本章之后 你将学会以下几个知识点 1 如何注册相机相关的权限 2

大家好,我是讯享网,很高兴认识大家。

上一章《Camera2 概览》里我们介绍了一些 Camera2 的基础知识,但是并没有涉及太多的 API,从本章开始我们会开发一个具有完整相机功能的应用程序,并且将相机知识分成多个篇章进行介绍,而本章所要介绍的就是相机的开启流程。

阅读本章之后,你将学会以下几个知识点:

1.如何注册相机相关的权限
2.如何配置相机特性要求
3.如何开启相机
4.如何关闭相机

1 创建相机项目

正如前所说的,我们会开发一个具有完整相机功能的应用程序,所以第一步要做的就是创建一个相机项目,这里我用 AS 创建了一个叫 Camera2Sample 的项目,并且有一个 Activity 叫 MainActivity。我们使用的开发语言是 Kotlin,所以如果你对 Kotlin 还不熟悉的话,建议你先去学习下 Kotlin 的基础知识。

为了降低源码的阅读难度,我不打算引入任何的第三方库,不去关注性能问题,也不进行任何模式上的设计,大部分的代码我都会写在这个 MainActivity 里面,所有的功能的实现都尽可能简化,让阅读者可以只关注重点。

2 注册相关权限

在使用相机 API 之前,必须在 AndroidManifest.xml 注册相机权限 android.permission.CAMERA,声明我们开发的应用程序需要相机权限,另外如果你有保存照片的操作,那么读写 SD 卡的权限也是必须的:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.camera2demo"> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" /> </manifest>

讯享网

需要注意的是 6.0 以上的系统需要我们在程序运行的时候进行动态权限申请,所以我们需要在程序启动的时候去检查权限,有任何一个必要的权限被用户拒绝时,我们就弹窗提示用户程序因为权限被拒绝而无法正常工作:

讯享网List<String> requiredPermissions = Arrays.asList(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE); private void checkPermissions() { List<String> unGrantedPermissions = new ArrayList<>(); for (String permission : requiredPermissions) { if (PackageManager.PERMISSION_GRANTED != checkSelfPermission(permission)) { unGrantedPermissions.add(permission); } } if (unGrantedPermissions.size() != 0) { requestPermissions(unGrantedPermissions.toArray(new String[unGrantedPermissions.size()]), 0); } }

3 配置相机特性要求

你一定不希望用户在一台没有任何相机的手机上安装你的相机应用程序吧,因为那样做是没有意义的。所以接下来要做的就是在 AndroidManifest.xml 中配置一些程序运行时必要的相机特性,如果这些特性不支持,那么用户在安装 apk 的时候就会因为条件不符合而无法安装


讯享网

<uses-feature android:name="android.hardware.camera" android:required="true"/> <uses-feature android:name="android.hardware.camera.autofocus" android:required="true"/>

我们通过 <uses-feature> 标签声明了我们的应用程序必须在具有相机的手机上才能运行。另外你还可以配置更多的特性要求,例如必须支持自动对焦的相机才能运行你的应用程序,更多的特性可以在 官方文档 上查询。

4 获取 CameraManager 实例

CameraManager 是一个负责查询和建立相机连接的系统服务,可以说 CameraManager 是 Camera2 使用流程的起点,所以首先我们要通过 getSystemService() 获取 CameraManager 实例:

讯享网CameraManager cameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);

5 获取相机 ID 列表

try { String[] cameraLis= cameraManager.getCameraIdList(); } catch (CameraAccessException e) { e.printStackTrace(); }

6 根据相机 ID 获取 CameraCharacteristics

CameraCharacteristics 是相机信息的提供者,通过它我们可以获取所有相机信息,这里我们需要根据摄像头的方向筛选出前置和后置摄像头,并且要求相机的 Hardware Level 必须是 FULL 及以上,所以首先我们要获取所有相机的 CameraCharacteristics 实例,涉及的 API 是 CameraManager.getCameraCharacteristics(),它会根据你指定的相机 ID 返回对应的相机信息:

讯享网String[] cameraIdList; try { cameraIdList= cameraManager.getCameraIdList(); CameraCharacteristics characteristics; for (String cameraId :cameraIdList) { characteristics = cameraManager.getCameraCharacteristics(cameraId); int facing = characteristics.get(CameraCharacteristics.LENS_FACING); int level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); Log.e(TAG, "facing = " + facing + ", level = " + level); } } catch (CameraAccessException e) { e.printStackTrace(); }

7 开启相机

接下来我们要做的就是调用 CameraManager.openCamera() 方法开启相机了,该方法要求我们传递两个参数,一个是相机 ID,一个是监听相机状态的 CameraStateCallback。当相机被成功开启的时候会通过 CameraStateCallback.onOpened() 方法回调一个 CameraDevice 实例给你,否则的话会通过 CameraStateCallback.onError() 方法回调一个 CameraDevice 实例和一个错误码给你。onOpened() 和 onError() 其实都意味着相机已经被开启了,唯一的区别是 onError() 表示开启过程中出了问题,你必须把传递给你的 CameraDevice 关闭,而不是继续使用它,具体的 API 介绍可以自行查看文档。另外,你必须确保在开启相机之前已经被授予了相机权限,否则会抛权限异常。一个比较稳妥的做法就是每次开启相机之前检查相机权限。下面是主要代码片段:

private String getBackCameraId(CameraManager cameraManager) { try { String[] cameraIdList = cameraManager.getCameraIdList(); CameraCharacteristics characteristics; for (String cameraId : cameraIdList) { characteristics = cameraManager.getCameraCharacteristics(cameraId); int facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (CameraCharacteristics.LENS_FACING_BACK == facing) { return cameraId; } } } catch (CameraAccessException e) { e.printStackTrace(); } return null; } private void openCamera(CameraManager cameraManager, String cameraId) { if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return; } try { cameraManager.openCamera(cameraId, callback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private CameraDevice.StateCallback callback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { Toast.makeText(MainActivity.this, "相机已开启", Toast.LENGTH_LONG).show(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { } @Override public void onError(@NonNull CameraDevice camera, int error) { camera.close(); } };

8 关闭相机

和其他硬件资源的使用一样,当我们不再需要使用相机时记得调用 CameraDevice.close() 方法及时关闭相机回收资源。关闭相机的操作至关重要,因为如果你一直占用相机资源,其他基于相机开发的功能都会无法正常使用,严重情况下直接导致其他相机相关的 APP 无法正常使用,当相机被完全关闭的时候会通过 CameraStateCallback.onCllosed() 方法通知你相机已经被关闭。那么在什么时候关闭相机最合适呢?我个人的建议是在 onPause() 的时候就一定要关闭相机,因为在这个时候相机页面已经不是用户关注的焦点,大部分情况下已经可以关闭相机了。

讯享网@Override protected void onPause() { super.onPause(); if (cameraDevice != null) { cameraDevice.close(); } }

至此,关于开关相机的教程就结束了,下一章我们会介绍如何开启预览。

源码:https://github.com/shouwang178/Android/tree/master/Camera2Demo

小讯
上一篇 2025-03-30 16:48
下一篇 2025-02-20 08:31

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/123956.html