Android Camera2 使用總結

2021-02-19 鴻洋

作者:_小河馬

連結:http://www.jianshu.com/p/73fed068a795

本文由作者投稿。

最近在做自定義相機相關的項目,網上查了資料都是有關android.hardware.Camera的資料,開始使用的才發現這個類已經廢棄了。
Android 5.0(21)之後android.hardware.Camera就被廢棄了,取而代之的是全新的android.hardware.Camera2 。
Android 5.0對拍照API進行了全新的設計,新增了全新設計的Camera v2 API,這些API不僅大幅提高了Android系統拍照的功能,還能支持RAW照片輸出,甚至允許程序調整相機的對焦模式、曝光模式、快門等。demo 地址https://github.com/Hemumu/WallpaperDemo

Camera2主要的類說明


CameraManager:攝像頭管理器。這是一個全新的系統管理器,專門用於檢測系統攝像頭、打開系統攝像頭。除此之外,調用CameraManager的getCameraCharacteristics(String)方法即可獲取指定攝像頭的相關特性。

CameraCharacteristics:攝像頭特性。該對象通過CameraManager來獲取,用於描述特定攝像頭所支持的各種特性。

CameraDevice:代表系統攝像頭。該類的功能類似於早期的Camera類。

CameraCaptureSession:這是一個非常重要的API,當程序需要預覽、拍照時,都需要先通過該類的實例創建Session。而且不管預覽還是拍照,也都是由該對象的方法進行控制的,其中控制預覽的方法為setRepeatingRequest();控制拍照的方法為capture()。

CameraRequest和CameraRequest.Builder:當程序調用setRepeatingRequest()方法進行預覽時,或調用capture()方法進行拍照時,都需要傳入CameraRequest參數。CameraRequest代表了一次捕獲請求,用於描述捕獲圖片的各種參數設置,比如對焦模式、曝光模式……總之,程序需要對照片所做的各種控制,都通過CameraRequest參數進行設置。CameraRequest.Builder則負責生成CameraRequest對象。


開啟相機請一定添加相關的相機權限,判斷6.0以後添加動態權限的獲取。如果相機預覽出現黑屏多半就是因為沒有相機權限而導致的

<uses-permission android:name="android.permission.CAMERA" /><uses-feature android:name="android.hardware.camera" /><uses-feature android:name="android.hardware.camera.autofocus" />

首頁我們要設置相機相關的參數

通過getSystemService(Context.CAMERA_SERVICE);拿到了CameraManager 返回當前可用的相機列表,在這裡你可以選擇使用前置還是後置攝像頭。

CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);可以拿到當前相機的相關參數,在這裡你可以進行相關的參數檢查,例如檢查閃光燈是否支持等。在這裡我們拿到當前相機的cameraId後面使用。

拿到cameraId我們就可以調用CameraManager的openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)打開相機了

添加 CameraDevice.StateCallback  監聽

我們需要對相機狀態就行監聽,以便在相機狀態發生改變的時候做相應的操作。openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)中CameraDevice.StateCallback就是對相機的狀態改變的Callback

創建 CameraCaptureSession

在onOpened()中我們可以拿到CameraDevice對象,在相機打開後需要創建CameraCaptureSession。


CameraCaptureSession是什麼呢?由於Camera2是一套全新的API,所以它引用了管道的概念將安卓設備和攝像頭之間聯通起來,系統向攝像頭髮送 Capture 請求,而攝像頭會返回 CameraMetadata。這一切建立在一個叫作 CameraCaptureSession的會話中。如下圖:

圖片來自http://wiki.jikexueyuan.com/project/android-actual-combat-skills/android-hardware-camera2-operating-guide.html

這裡我們需要預覽相機的內容就需要創建CameraCaptureSession向相機發送Capture請求預覽相機內容

首先我們創建了一個CaptureRequest 上面說過了我們需要跟相機通信只有通過CameraCaptureSession。而要和CameraCaptureSession通信就是發送請求。這裡我們相當於在創建請求的一些參數。

createCaptureRequest(int); 也有很多參數可選。

這裡我們發送的是CameraDevice.TEMPLATE_PREVIEW也就是告訴相機我們只需要預覽。更多參數如下:

TEMPLATE_RECORD   創建適合錄像的請求。

TEMPLATE_PREVIEW 創建一個適合於相機預覽窗口的請求。

TEMPLATE_STILL_CAPTURE 創建適用於靜態圖像捕獲的請求

TEMPLATE_VIDEO_SNAPSHOT  在錄製視頻時創建適合靜態圖像捕獲的請求。

詳細信息可以參考官網的API文檔。

調用創建方法createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler) 第一參數就是我們需要輸出到的Surface列表,這裡我們可以輸出到一個SurfaceView中或者TextureView中。

第二參數是對創建過程的一個回調方法,當onConfigured回調的時候說明CameraCaptureSession創建成功了。

現在我們可以向CameraCaptureSession發送前面創建的好的預覽相機請求了。調用mCaptureSession.setRepeatingRequest(mPreviewRequest,null, mBackgroundHandler); 這樣我們就開啟的相機的預覽,在剛才添加的輸出Surface對應的控制項中我們可以看到攝像頭的預覽內容了。

當我們需要拍照並且得到相應的照片數據的時候和開啟相機預覽相同的操作,我們只需要向CameraCaptureSession發送我們創建好的請求就行,就像我們請求網絡數據一樣,封裝好參數直接告訴CameraCaptureSession需要做什麼由它去和相機建立通信並執行相應的操作。

對焦


向CameraCaptureSession發送對焦請求,並且對對焦是否成功進行監聽,在mCaptureCallback中對回調進行處理


拍攝圖片

對焦完成後我們就可以向CameraCaptureSession發送請求可以拍照了

相信看到這裡代碼已經不複雜了,組裝好我們的請求然後用CameraCaptureSession發送這個請求就可以了。

這裡需要注意的是我們怎麼拿到圖片數據呢? 這裡要說回在創建CameraCaptureSession時參數不是有一個輸出的Surface列表麼,在列表中添加一個ImageReader的Surface用戶獲取圖片數據

mCameraDevice    .createCaptureSession(        Arrays.asList(surface, mImageReader.getSurface()),null)

在ImageReader中對圖片獲取就行監聽

調用reader.acquireNextImage()我們就可以拿到當前的圖片數據了。拍完後我們需要解鎖焦點讓相機回到預覽狀態,同樣的我們發送請求就可以了

效果

之前看了鴻神推送的Android 仿火螢視頻桌面 神奇的LiveWallPaper 一文中提到了用相機來做壁紙也就是透明屏幕,項目地址https://github.com/songixan/Wallpaper 查看源碼發現還是用的舊的CameraAPI,所以我在Demo中用Camera2API做了透明屏幕,有興趣的可以去看下。  

PS:後來在同事的小米2S(5.1.1)中測試發現出錯了,初步猜測是解析度的原因,目前正在解決中。有問題大家可以私信我 謝謝~

到此Camera2的學習就結束了,同樣的如果你想用相機就行拍攝視頻也是如此,用CameraCaptureSession發送相應的請求了就可以了,大家有興趣可以做一做視頻的拍攝。現在做微信的小10秒小視頻拍攝也很簡單了,思路很簡單當用戶按下拍攝按鈕用CameraCaptureSession發送拍攝視頻的請求,鬆開手指的時候相機恢復到預覽狀態。so easy~ 大家有興趣可以嘗試下。
拍攝視頻的Demohttps://github.com/googlesamples/android-Camera2VideoTinks android.hardware.camera2 使用指南
http://wiki.jikexueyuan.com/project/android-actual-combat-skills/android-hardware-camera2-operating-guide.html

如果你有想學習的文章直接留言,我會整理徵稿。如果你有好的文章想和大家分享歡迎投稿,直接向我投遞文章連結即可。

歡迎長按下圖->識別圖中二維碼或者掃一掃關注我的公眾號:

相關焦點

  • 【Android】CameraX-CameraView說明
    官方為了讓我們更容易使用Camera,出了個一個官方的庫cameraview。不過這個庫已經Deprecated,官方建議使用Jetpack CameraX 替代。CameraX基本上分為三部分,一部分控制拍照,一部分控制錄製視頻,還有一部分時進行視頻和照片的預覽。
  • [Android進階]使用Camera2 API實現一個相機預覽頁面
    Camera2 API(位於android.hardware.camera2包下)是Android L後推出的一套訪問攝像頭設備的接口,用來替換原有的Camera。><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height
  • Camera2/HAL3 框架分析 程式設計師Android
    進程中分離出來,作為一個獨立進程 android.hardware.camera.provider@2.4-service 用來控制 camera HAL,cameraserver通過 HIDL 機制於camera provider進行通信。
  • 【camera hal 系列之一】android camera HAL v3.0概述
    Android的camera硬體抽象層(HAL)將更高層次的android.hardware.Camera中的camera框架層API與底層的camera驅動和camera硬體模塊連接了起來。android最新版本介紹了camera棧的一個新的、底層的實現。
  • Android Camera2 實現高幀率預覽錄製(附源碼)
    :name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE
  • Android Camera SurfaceView 預覽拍照
    = null) {            throw new RuntimeException("camera already initialized!"),而我們實際項目中在使用到這兩項權限時,需要你檢查權限是否已經被授權,如果沒授權,則需要請求授權:<!
  • Android Jetpack CameraX 庫 Beta 版正式發布!
    forum/camerax-developers新建一個 issuehttp://issuetracker.google.com/官方文檔https://developer.android.google.cn/training/camerax官方示例代碼https://github.com/android/camera-samples
  • 使用 CameraX Extensions API 將特效應用到照片上
    implementation 'androidx.camera:camera-camera2:1.1.0-alpha08' implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha08' implementation 'androidx.camera:camera-extensions:1.0.0-alpha28
  • Android平臺Camera開發指南
    版本兼容性問題,Android 5.0以下的Camera和Android 5.0以上使用Camera2,Android 4.0以下的SurfaceView和Android 4.0以上的TextureView,Android 6.0以上要做相機等運行時權限兼容。
  • Android Multimedia框架總結(十六)Camera2框架之openCamera及session過程
    前言:前一篇介紹了Camera2相關類作用及功能,並未對源碼部分了解,今天了解了在Camera2框架中openCamera及session過程,
  • Camera2 / HAL3 架構了解下
    進程中分離出來,作為一個獨立進程 android.hardware.camera.provider@2.4-service 用來控制 camera HAL,cameraserver通過 HIDL 機制於camera provider進行通信。
  • Android Camera/Camera2開發指南
    版本兼容性問題,Android 5.0以下的Camera和Android 5.0以上使用Camera2,Android 4.0以下的SurfaceView和Android 4.0以上的TextureView,Android 6.0以上要做相機等運行時權限兼容。
  • Camera 入門第一篇 openCamera
    四、CameraService.connectDevice五、CameraManager.setRemoteDevice一、openCamera 簡單調用流程打開相機是通過調用CameraManager.java (frameworks\base\core\java\android\hardware\camera2)的 openCamera 方法,根據指定的CameraId
  • 使用camera2+zxing打造一個簡易的掃碼工具
    ' is deprecated as of API 21: Android 5.0 (Lollipop)原因是掃碼工具中使用的camera API已經廢棄,查看Camera類,可以看到javadoc的註解描述寫著建議使用新API的camera2。
  • Google Camera 架構了解下
    原圖:https://source.android.google.cn/devices/camera1.1 Android Camera 基本分層Google Android 框架圖從上圖得知,Android手機中Camera軟體主要有大體上有4層:1.應用層:應用開發者調用AOSP提供的接口即可,AOSP的接口即Android
  • CameraX 曝光補償 API 入門指南
    /camera/core/ExposureState我們來看看在 CameraX 應用中如何使用 API 來創建曝光合適的照片。要在應用中使用曝光補償 API,您需要完成如下工作:曝光補償值的範圍依賴相機設備的配置和硬體級別;應用可以通過 ExposureState 接口查詢所支持的取值範圍:https://developer.android.google.cn/reference/android/hardware/camera2/CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
  • camera hal1-open流程(1)
    /device/CameraHardwareInterface.hframework中,camera.java是管理和提供給上層APP的各種API接口android/frameworks/base/core/java/android/hardware/Camera.javapublic static Camera openLegacy
  • Camera 入門第一篇
    四、CameraService.connectDevice五、CameraManager.setRemoteDevice一、openCamera 簡單調用流程打開相機是通過調用CameraManager.java (frameworks\base\core\java\android\hardware\camera2)的 openCamera 方法,根據指定的CameraId
  • Android CameraView 實用經驗分享
    修復了一個可能是 BUG 的 BUG;2. 加入手動對焦功能,效果基本和原生相機一致。="http://schemas.android.com/apk/res/android">    <TextureView        android:id="@+id/texture_view"        android:layout_width="match_parent"        android:layout_height="match_parent
  • Camera Open 流程源碼分析
    } 2.CameraManager.java(frameworks\base\core\java\android\hardware\camera2)CameraManager 會根據傳遞過來的參數不同,調用不同的Opencamera 方法。