文章目录
1. 介绍
本文档是对于 android.hardware.Camera 的一个使用说明文档,主要帮助自己加强对于Camera的理解和使用,同时也是对Camera上层代码的源码进行一个翻译,说明各个方法的作用以及一些参数的实际效果,为以后能快速使用Camera进行开发提供一份详细的参考文档。
本文档适用于初、中级的Camera方向的研发人员。可以作为快速入门的文档,引导和帮助大家更好的了解源码,同时也可以作为在开发过程中的工具书。由于没有深入jni层研究,所以在一些方面难免存在瑕疵,希望大家多多交流和指正。
2. Camera 详解
大家首先要注意,我们使用的Camera的包路径是android.hardware.Camera,所以在使用时需要注意不要把路径搞错了。
Camera是Android通过Java层调用系统相机的类,对于Camera的实际操作都是驱动层写好了的,Java层只能进行的一些简单的操作,包括常用的配置、常用的功能以及一些数据、状态的回调。Camera可供我们调用的常用方法如下:
- open() : 打开摄像头
- getParameters() : 获取Camera.Parameters
- setParameters() : 设置Camera.Parameters
- setPreviewDisplay() : 设置用于预览图输出的SurfaceView
- setPreviewTexture() : 设置用于预览图输出的SurfaceTexture
- startPreview() : 开始预览
- stopPreview() : 结束预览
- setPreviewCallback() : 设置预览的回调
- setOneShotPreviewCallback() : 设置下一帧预览图像的回调
- takePicture() : 拍照,并回调结果到传入的Callback中
- autoFocus() : 进行一次自动对焦并回调
- cancelAutoFocus() : 取消自动变焦
- setAutoFocusMoveCallback() : 设置自动对焦时的回调
- startSmoothZoom() : 设置焦距,动态改变
- stopSmoothZoom() : 关闭设置焦距时的动态
- setZoomChangeListener() : 设置变焦的监听
- setDisplayOrientation() : 设置预览图的旋转角度(0,90,180,270)
- enableShutterSound() : 打开/关闭拍照时的声音
- startFaceDetection() : 开启人脸识别
- stopFaceDetection() : 关闭人脸识别
- setFaceDetectionListener() : 设置人脸识别的监听
- release() : 释放设备
在这些方法中,都没有太复杂的逻辑,不过关于Camera的使用,有些特点我们需要注意:
- Camera是系统唯一的,如果你的App占用了Camera,其它App将不能再通过调用open()方法打开摄像头。所以,我们需要在App进入后台状态,或者退出相机界面后,调用Camera.release()将Camera相关的资源释放掉。
- open()只是打开了摄像头,并没有开始预览,所以在startPreview()之前,PreviewCallback.onPreviewFrame()不会调用。
- setOneShotPreviewCallback()设置的回调只会设置一次调用一次。
- 如果open()和startPreview()在短时间内顺序执行了,可能会出现开始预览失败的情况。
3. Camera.Params
Camera.Params提供了Java上层能对摄像机参数进行的全部配置,也是我们在使用相机时最需要去了解的内容。从源码中我们可以了解到,Params内部维护了一个LinkedHashMap,而我们进行的一些配置,都是通过put方法放入到map中去的,它提供了很多KEY供给用户进行设置,也会有一些没有公开定义的Key,我们可以通过拼接的方式完成,比如:
获取支持的分辨率熟悉的key :KEY_PREVIEW_SIZE + SUPPORTED_VALUES_SUFFIX
可能还有一些我们不知道的key可以对摄像头进行配置的,就需要我们自己去网上找解决方案。
下面,会针对这个类里面的已有的全部参数进行说明。
3.1 预览图大小
设置预览图大小需要调用的方法一般有下面几个方法:
- params.getSupportedPreviewSizes():获取手机支持的预览效果的分辨率
- params.setPreviewSize(width,height):设置预览效果的分辨率
由于手机一般是支持多种分辨率的,所以我们在调用setPreviewSize之前,需要找到和我们屏幕适配的预览大小,具体方法如下:
private static Point findBestPreviewSizeValue(List<Camera.Size> supportSizeList, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (Camera.Size previe