一、需求背景
有必要讲一下需求的背景,防止被想歪。
背景:在一块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 文档查找两把利器

更多相关文章

  1. Camera360 3.0 Android手機攝影大師洗心革面速度大升級
  2. Android(安卓)Studio官方文档之使用布局编辑器来设计UI界面
  3. Android(安卓)Camera生成bmp格式的图片
  4. Android短信管家(确认需求)1
  5. Android(安卓)拍照声音问题(声音大小不可变、音量按键无法调节大
  6. Android(安卓)OpenGLES2.0(十一)——利用OpenGLES做Camera预览
  7. android调用摄像头拍照,从相册中选择照片并裁剪
  8. Android(安卓)O预览版有哪些缺点?Android(安卓)O预览版火速刷机
  9. Android(安卓)WebView保存登陆cookie

随机推荐

  1. Android应用开发学习笔记之播放音频
  2. 在Android中加入GOOGLE统计系统
  3. android textview 中超出屏幕宽度的字符
  4. Delphi XE5的Android开发平台搭建
  5. android命令行启动
  6. android启动界面说明
  7. Android(安卓)TabHost学习笔记
  8. Android(安卓)Data Binder 的一个bug
  9. Android中使用ormlite实现持久化--HelloO
  10. Android中使用listview实现qq/微信好友列