記錄需求-在Service中拍照

1、需求背景
有必要講一下需求的背景,防止被想歪。
背景:在一塊Android的開發板上,有HDMI的輸入接口,驅動層已經作了封裝,將HDMI輸入的視頻源轉成CameraApi提供給應用層調用;也就是說在Android應用中,只需調用攝像頭,就能夠獲取視頻源;
需求:要求在不展現界面的狀況下(Service中),對視頻源進行截屏,也就是拍照。session

2、探索過程
板子上Android的版本是6.0;攝像頭的Api是Camera2.0。
經過谷歌官方的例子,能夠看到一個正常拍照的流程以下
openCamera(開啓設備,啓動HandleThread)->
createCameraPreviewSession(建立預覽會話)->
setRepeatingRequest(開始預覽)->
capatrue(拍照請求)ide

考慮需求,着重看了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:oop

camera.createCaptureSession(Arrays.asList(imageReaderSurface), new  
  CameraCaptureSession.StateCallback()

第二點在於改按鈕觸發爲直接拍照,原有代碼中,是先進行預覽的請求TEMPLATE_PREVIEW,然後按鈕觸發再發出TEMPLATE_STILL_CAPTURE獲取靜態畫面,咱們改爲在建立會話的回調中,一旦狀態就緒,就發出保存圖片的請求:fetch

//獲取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中打開攝像頭,攝像頭開啓完畢後,創建捕獲對話,完成後發送請求保存文件,
至此需求就完成了。
3、延申
一、涉及以下的知識點
a:SurfaceView、TextureView、View的區別
官方的代碼中,使用了TextureView來進行預覽ui

b:HandlerThread
HandlerThread爲綁定了Handler的線程,本拍照程序中,應用在後臺啓動HandlerThread,主線程中在完成了相應的準備後,經過thread綁定的handler向其發送消息。
HandlerThread和Thread的不一樣在於內部有Looper和Handler,能夠接收消息。至關於把綁定handler和thread的操做封裝到內部。
image.pngspa

二、安利工具:DocFetch-文件內容搜索器
寫這篇博客的時候,離當時研究這個需求已通過去了一年多,項目文檔已經淹沒在大批的項目中找不到了,只能記得文件裏面關於createCaptureSession的內容,經過文件搜索沒法定位,只能去找查找文件內容的工具,最後找到了DocFetch;
在工程目錄創建索引花了10幾分鐘,以後順利得找到了須要的工程。
image.png
具體的操做能夠看參考連接中的文章。
4、參考連接
HandlerThread解析
Everything+Docfetcher 文檔查找兩把利器線程

相關文章
相關標籤/搜索