记录需求-在Service中拍照
一、需求背景
有必要讲一下需求的背景,防止被想歪。
背景:在一块Android的开发板上,有HDMI的输入接口,驱动层已经做了封装,将HDMI输入的视频源转成CameraApi提供给应用层调用;也就是说在Android应用中,只需调用摄像头,就可以获取视频源;
需求:要求在不展示界面的情况下(Service中),对视频源进行截屏,也就是拍照。
二、探索过程
板子上Android的版本是6.0;摄像头的Api是Camera2.0。
通过谷歌官方的例子,可以看到一个正常拍照的流程如下
openCamera(开启设备,启动HandleThread)->
createCameraPreviewSession(创建预览会话)->
setRepeatingRequest(开始预览)->
capatrue(拍照请求)
考虑需求,着重看了createCameraPreviewSession这一步,其中部分代码如下:
// This is the output Surface we need to start preview. Surface surface = new Surface(texture); // We set up a CaptureRequest.Builder with the output Surface. mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE\_PREVIEW); mPreviewRequestBuilder.addTarget(surface); // Here, we create a CameraCaptureSession for camera preview. mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback()
可以看到,createCaptureSession方法中第一个参数为surface列表,代码中列表中为,预览界面及拍照存储的Surface;
为在Service中拍照,自然没有预览的界面,所以把列表中的第一个用于预览的surface删除,保留用于保存文件的surface:
camera.createCaptureSession(Arrays.asList(imageReaderSurface), new CameraCaptureSession.StateCallback()
第二点在于改按钮触发为直接拍照,原有代码中,是先进行预览的请求TEMPLATE_PREVIEW,而后按钮触发再发出TEMPLATE_STILL_CAPTURE获取静态画面,我们改成在创建会话的回调中,一旦状态就绪,就发出保存图片的请求:
//获取ImageReader的Surface Surface imageReaderSurface = mImageReader.getSurface(); mCaptureRequestBuilder = camera.createCaptureRequest(CameraDevice .TEMPLATE_STILL_CAPTURE); //CaptureRequest添加imageReaderSurface, // 不加的话就会导致ImageReader的onImageAvailable // ()方法不会回调 mCaptureRequestBuilder.addTarget(imageReaderSurface); camera.createCaptureSession(Arrays.asList(imageReaderSurface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { try { session.capture(mCaptureRequestBuilder.build(), null, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { } }, null);// 关闭相机时别忘了关闭ImageReader } catch (CameraAccessException e) { e.printStackTrace(); }
代码中的mCaptureRequestBuilder设置为TEMPLATE_STILL_CAPTURE捕获静态画面捕捉。
全过程为在Service中create中打开摄像头,摄像头开启完毕后,建立捕获对话,完成后发送请求保存文件,
至此需求就完成了。
三、延申
1、涉及如下的知识点
a:SurfaceView、TextureView、View的区别
官方的代码中,使用了TextureView来进行预览
b:HandlerThread
HandlerThread为绑定了Handler的线程,本拍照程序中,应用在后台启动HandlerThread,主线程中在完成了相应的准备后,通过thread绑定的handler向其发送消息。
HandlerThread和Thread的不同在于内部有Looper和Handler,可以接收消息。相当于把绑定handler和thread的操作封装到内部。
2、安利工具:DocFetch-文件内容搜索器
写这篇博客的时候,离当时研究这个需求已经过去了一年多,项目文档已经淹没在大批的项目中找不到了,只能记得文件里面关于createCaptureSession的内容,通过文件搜索无法定位,只能去找查找文件内容的工具,最后找到了DocFetch;
在工程目录建立索引花了10几分钟,之后顺利得找到了需要的工程。
具体的操作可以看参考链接中的文章。
四、参考链接
HandlerThread解析
Everything+Docfetcher 文档查找两把利器
更多相关文章
- Camera360 3.0 Android手機攝影大師洗心革面速度大升級
- Android(安卓)Studio官方文档之使用布局编辑器来设计UI界面
- Android(安卓)Camera生成bmp格式的图片
- Android短信管家(确认需求)1
- Android(安卓)拍照声音问题(声音大小不可变、音量按键无法调节大
- Android(安卓)OpenGLES2.0(十一)——利用OpenGLES做Camera预览
- android调用摄像头拍照,从相册中选择照片并裁剪
- Android(安卓)O预览版有哪些缺点?Android(安卓)O预览版火速刷机
- Android(安卓)WebView保存登陆cookie