不扯闲嗑,直接上干货。想看代码可以去搜官方提供的代码。
1 功能分布
Activity中加载TextureView,实现预览
Service中实现Camera2功能
2 初步使用
2.1 Activity中
TextureView在XML中设置为隐藏状态android:visibility="invisible"
TextureView设置监听TextureView.SurfaceTextureListener,等待TextureView准备完毕回调onSurfaceTextureAvailable。这个回到方法中携带的参数SurfaceTexture是Camera2实现预览的关键对象。
2.2 Service中
开启Camera2的流程:权限判断-->获取CameraManager-->选择摄像头-->openCamera
Camera2运行需要另起线程mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
预览和拍照状态下通过ImageReader获取照片,在setOnImageAvailableListener监听里获取图片数据
说明:因为Camera2是在Service中完成的,这就涉及到Activity与Service的一个绑定过程A。Camera2要实现预览需要等待TextureView的onSurfaceTextureAvailable回调过程B。都是异步过程,控制起来相对麻烦些,那就人为的给排个序。等过程A执行完毕后,将TextureView由隐藏设置为显示,这时过程B将会被激活。
注意:1 TextureView初始时是隐藏状态,会处在一种不可用的状态。
2 要在TextureView由隐藏设置为显示之前,设置好TextureView.SurfaceTextureListener
2.3 简述预览功能流程
1 权限确认
2 获取CameraManager
获取到将要是使用的摄像头ID
3 openCamera
通过摄像头ID,在线程中启动,需要加入openCamera的状态监听
4 监听CameraDeveices.stateCallback
通过摄像头ID
可以获取到CameraDeveice
通过CameraDevice设置Camera模式(这里设置为预览模式)
获取到CaptureRequest
在CaptureRequest添加Surface(预览控件,与ImagerReader)
启动CaptureSession, 通过Surface(预览控件,与ImagerReader),加入监听
5 CaptureSession监听中
获取到CameraCaptureSession
可通过之前的CaptureRequest设置曝光、对焦等信息
通过Session设置捕获图像数据的模式:单次、无限循环等。预览功能用无限循环模式
这之后就能通过预览和通过ImagerReader获取图片数据了。
3 准备拍照
3.1 openCamera
需要先判断是否获取到Camera权限,如果没有获取到,需要做个权限提示,当收到权限被获取的回到后再openCamera。
这里涉及到CameraDevice.StateCallback监听,在监听到onOpened回调后,可以获取到代码意义上的Camera设备CameraDevice。在回调中可做Surface的设置,如果涉及到预览与预览图片获取,那么就把TextureView的Surface与ImagerReader的Surface添加到CameraDevice设备中。并设置Camera的运行模式TEMPLATE_PREVIEW(预览)。
3.2 CameraCaptureSession
相机捕获会话,这个概念就得意会了,说不清楚。我的理解就是Camera捕获模式的控制者,预览模式:持续捕获相机数据,拍照模式:捕获一次相机数据 等等。
在onOpened回到后执行CameraDevice.createCaptureSession,等待回调CameraCaptureSession.StateCallback,当收到onConfigured回调方法后,便可以获取到CameraCaptureSession对象,这时就可以控制Camera的不同模式了(预览模式:持续捕获相机数据,拍照模式:捕获一次相机数据 等等)
说明:1 预览模式下,使用CameraCaptureSession.setRepeatingRequest方法,便可以无休止地重复捕获映像,如果有ImagerReader可将数据转化成图片。
2 拍照模式下,CameraCaptureSession.capture方法,只做一次捕获请求。
注意:在捕获请求是可以注册监听CameraCaptureSession.CaptureCallback,与可以使用null,具体需要看实际需求了
3.3 CaptureRequest.Builder
当设置Camera的模式时(TEMPLATE_PREVIEW 预览模式),CameraDevice.createCaptureRequest( CameraDevice.TEMPLATE_PREVIEW),会得到CaptureRequest.Builder对象获取请求,可对该模式进行一下属性设置:曝光,对焦,Sureface,获取图片的转角 等等。
说明:需要通过CameraCaptureSession完成本次请求
注意:在切换模式时需要先用:
CameraCaptureSession.stopRepeating();
CameraCaptureSession.abortCaptures();
4 拍照控制
4.1 指定焦点拍照
设置焦点范围Rect,设置曝光区域,设置对焦区域:
CaptureRequest.set(CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[]{new MeteringRectangle(rect, 1000)});
CaptureRequest.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{new MeteringRectangle(rect, 1000)});
4.2 对焦后获取图片
请求一次CaptureRequest流程(CaptureSession.capture()),在capture()中注入回调信息,监视到对焦完成后,进行拍照处理。
新建拍照模式TEMPLATE_STILL_CAPTURE的CaptureRequest,停止CameraCaptureSession的预览,执行拍照的capture,会在ImagerReader中的到图片数据
4.3 拍照后恢复预览模式
注意:Camera2可以做到无预览拍照,再也不用偷偷摸摸的设1像素Activity了。在设置添加surface时,不加入预览控件的surface,只加入ImagerReader的surface。