2021SC@SDUSC
目录
前言
上几篇文章已经分析完了飞花令的项目,从这一篇开始分析camera的项目。开发人员的设计中,以手机相机为依托的camera项目不仅需要有基础的拍照功能,并且还需要对拍摄的照⽚进⾏⼀系列处理,包括但不仅限于图⽚抗扭曲,曝光度,聚焦等。具体可以整理为以下功能:1. 相机预览功能
2. 拍照的偏好设置,如闪光灯,聚焦,曝光补偿
3. 相机可随设备旋转,拍摄横屏和竖屏的照⽚
4. 拍照后保存在⼿机的pictures⽂件夹
5. 可以预览拍摄的照⽚
6. 图⽚抗扭曲处理
这篇开始分析相机的预览功能。
一、项目环境
android studio版本 4.1.2
sdk版本 Compile SDK version:30
Build Tools Version 30.0.3
gradle版本 6.8.3
二、项目结构
项目代码放在java->com.example.camera下
布局文件放在res->layout里
偏好布局在xml里
三、代码分析
相机预览功能
相机预览功能就是我们在打开相机之后,进行拍照之前,出现在屏幕内的内容,我们拍照时往往根据预览的内容确定想要的效果来进行调整相机的角度等,开发人员在整个过程中还加入了参数的调整,比如闪光灯、对焦、曝光补偿三个功能。
1.CameraPreview类
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
}
软件开发人员定义了CameraPreview这个类,CameraPreview这个类继承了SurfaceView这个父类,并且SurfaceView 就是带 Surface 的 view,它是一个 View,是 View 的子类,所以和其他 View 一样,可以在屏幕上展示东西接收用户输入,具有 View 的生命周期回调函数,如 onMeasure、onLayout、onDraw、onTouchEvent 等
SurfaceView和View的区别
View | SurfaceView |
---|---|
适用于主动更新 | 适用于被动刷新 |
在主线程中进行画面更新 | 通常通过一个子线程来进行画面更新 |
绘图中没有使用双缓冲机制 | 在底层实现中就实现了双缓冲机制 |
同时CameraPreview还使用了SurfaceHolder.Callback接口。SurfaceHolder是一个接口,其作用就像一个关于Surface的监听器。在SurfaceView中有一个方法getHolder,可以很方便地获得SurfaceView所对应的Surface所对应的SurfaceHolder。SurfaceHolder提供访问和控制SurfaceView背后的Surface 相关的方法,它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。其实这一点是通过其内部的静态子接SurfaceHolder.Callback来实现的,这就是我们所用到的接口,SurfaceHolder.Callback中定义了三个接口方法:
-
abstract void surfaceChanged(SurfaceHolderholder, int format, int width, int height)
当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
-
abstract void surfaceCreated(SurfaceHolderholder)
当surface对象创建后,该方法就会被立即调用。
-
abstract void surfaceDestroyed(SurfaceHolderholder)
当surface对象在将要销毁前,该方法会被立即调用。
2.CameraPreview类中定义的变量
private static final String TAG = "CameraPreview";
private static Camera mCamera;
private SurfaceHolder mHolder;
SurfaceView是一个包含有Surface的View,而Surface用来处理直接呈现在屏幕上的内容,成员变量mHolder即为SurfaceHolder的实例,是保存这个Surface的“持有者”,只有Holder才能对对应的Surface进行修改。成员变量mCamera保存相机Camera的实例。
对于SurfaceView来说,这个View创建时就会创建Surface,而当Surface创建时就会触发我们上述所说的surfaceCreated(),所以我们就要在surfaceCreated()中打开相机、开始预览,并将预览帧交给Surface处理,要把这几个方法加入到surfaceCreated()方法中,达到点开app进行运行即可预览的目的。getCameraInstance()是一个获取并打开相机的方法。Camera的setPreviewDisplay()方法就是告知将预览帧数据交给谁,这里当然就是这个Surface的Holder了。最后用startPreview()开启相机,这就是一个初始化的顺序。
3.CameraPreview的构造方法
public CameraPreview(Context context) {
super(context);
mHolder = getHolder();//得到Surface所对应的Holder
mHolder.addCallback(this);//为SurfaceHolder添加一个SurfaceHolder.Callback回调接口
}
4.得到Camera实例
使用Camera类中的open()方法:
open开启默认相机(后置相机),open(int)开启特定相机,打开相机是可能失败的,所以一定要检查相机是否打开成功,判断Camera是否为null, mCamera = Camera.open(cameraID);
后置相机和前置相机id常量:CameraInfo.CAMERA_FACING_BACK, CameraInfo.CAMERA_FACING_FRONT
打开特定相机Camera.open(cameraid)。
private static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.d(TAG, "camera is not available");
}
return c;
}
四、总结
接触这个项目,明显感觉是比飞花令的难度大的,每个类、方法、层次架构都需要好好琢磨一下,而且感觉zip源码包和开发人员使用的源码有一些出入,还是需要认真研究一下。