十年Android程序員:探索Android CameraX

若是你曾經用過 Android 的 Camera APIs,你可能已經感覺到了,它們一直沒有成爲最容易實現的東西。最開始是 Camera API,而後又推薦使用 Camera2 API — 這個升級是爲了讓開發者在使用 Android 的相機 API 時有更好的體驗。然而,使用相機的 API (即便是最簡單的使用)時仍是會有不少髒代碼,並且,在 Android 應用中要實現 Camera 功能時仍是會很困難。android

幸運的是,新的 CameraX API 給相機功能開發提供了更簡單的解決方案以幫助咱們減輕這些痛苦。另外,CameraX 基於 Camera2 API 實現,它極大地簡化了在 minSdk 21 及以上版本的實現過程。這篇文章將會研究 CameraX API 的第一部分,瞭解 Camera API 是什麼以及咱們如何在 App 中開始使用它。bash

配置 CameraX架構

CameraX 由兩個概念來完成實現 -- Camera View 和 Camera Core。Camera View 可被單獨用於處理基本的相機要求,好比拍照,錄視頻,生命週期管理以及相機切換等。而核心庫可以搭配 Camera View 處理更復雜的 CameraX 實現(好比在當前的相機上下文提供一個取景器)。咱們將會在這篇文章中看看 CameraView 組件是怎麼工做的。app

開始使用 CameraX 以前,咱們須要一些配置步驟。放心,從添加權限到在你的 app 裏有一個簡單的 camera 實現,不會有不少步驟(甚至也不會有不少代碼)。ide

首先在應用的 manifest 添加 Camera 權限:佈局

<uses-permission android:name="android.permission.CAMERA" />
複製代碼

而後,須要添加必要的依賴:學習

def camerax_version = "1.0.0-alpha01"
// 添加 CameraX core 
「androidx.camera:camera-core:${camerax_version}」
// 添加 CameraX Camera2 API 互操做支持
implementation 「androidx.camera:camera-camera2:${camerax_version}複製代碼

**注意:**CamaraView 如今還不可用,但你能夠在這裏看源碼。由於這個緣由,實現的細節將來可能會有變化。this

你可能注意到了,這裏有兩個不一樣的依賴:spa

  • Camera Core 庫爲使用 CameraX 庫提供了必要的類
  • CameraX Camera2 依賴提供了一些互操做功能因此咱們可以在 CameraX 中集成一些已有的 Camera2 實現。

有了上面的準備工做,咱們如今能夠看看如何在咱們的應用裏實現 Camera view 組件了。code

Camera View

正如上文所說,CameraView 給開發者提供了方法,使他們不須要太多困難就能夠在 app 裏提供基礎的 camear 實現。咱們可以在佈局文件裏直接添加這個組件:

<androidx.camera.view.CameraView
 android:id="@+id/view_camera"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
複製代碼

這個 CameraView 類是一個 ViewGroup,本質上包含了一個 TextureView 來顯示 camera 流,以及配置這個組件的一些屬性。

  • scaleType—給捕獲的流設置縮放類型。可使 CENTER_CROP 或者 CENTER_INSIDE
  • quality—設置捕獲的媒體的質量。能夠是 MAX,HIGH,MEDIUM 或者 LOW
  • pinchToZoomEnabled—一個布爾值,控制用戶是否可以在 CameraView 內使用手指縮放視圖
  • captureMode—設置捕獲模式。能夠是 IMAGE,VIDEO 或者 FIXED
  • lensFacing—設置鏡頭。能夠是 FRONT,BACK 或者 NONE
  • flashMode—設置閃光燈模式。能夠是 FRONT,BACK 或者 NONE

這些 xml 屬性既能夠在佈局文件裏設置,也能夠在代碼裏設置。因此,若是你想提供 UI 控件控制上面這些屬性 ,你可使用 ClickListener 來設置這些屬性。

既然咱們是在 Activity 里布局的 CameraView,咱們能夠用 CameraView 的 bindToLifeCycle 方法將這個 View 與當前組件的生命週期綁定。

class MainActivity : AppCompatActivity() { 
 override fun onCreate(savedInstanceState: Bundle?) { 
 ...
 view_camera.bindToLifecycle(this) 
 }
}
複製代碼

前面所說的已經配置而且添加到咱們的工程了,如今咱們在 app 裏有了一個準備好了的簡單的 CameraView 來捕獲媒體。須要說明的是,CameraView 不能被單獨擴展來提供更多的功能。CameraView 的目標是提供一個簡化的能夠方便地以 View 的形式使用的相機實現。若是你想要實現更多的功能,你須要使用 CameraX Core 庫,咱們將在另外一篇文章裏聊到它。

若是你已經完成了上面的配置,那你應該可以打開相機而且在屏幕上看到預覽了。CameraView 提供了一些當用戶操做 UI 時咱們能夠觸發的方法。

  • toggleCamera—切換設備正在使用的相機(例如在前置和後置相機之間切換)
  • enableTorch—開啓閃光燈
  • setCameraByLensFacing—設置相機使用面向某個方向的鏡頭。能夠是 LensFacing.Back 或者 LensFacing.Front。
  • hasCameraWithLensFacing—檢測相機是否有與 LensFaing 值對應的鏡頭
  • focus—相機在指定矩形範圍內對焦

當要使用拍照功能時,takePicture 方法能夠從相機捕獲圖片。這裏咱們須要提供一個圖片數據保存位置的文件引用,以及一個在圖片成功保存或者出現錯誤時使用的 Listener。

camera_view.takePicture(File("some_file_path"),
 object : ImageCaptureUseCase.OnImageSavedListener {
 override fun onImageSaved(file: File) {
 // 處理被保存的圖片
 }
 override fun onError(
 error: ImageCaptureUseCase.UseCaseError,
 message: String,
 throwable: Throwable?
 ) {
 // 處理錯誤
 }
 })
複製代碼

當拍攝視頻出現錯誤是,ImageCaptureUseCase.UseCaseError 將會給咱們返回如下的某一錯誤狀態:

  • UNKNOWN_ERROR
  • FILE_IO_ERROR

takePicture 還有另外一種形式,這種形式只使用一個 OnImageCaptureListener 回調參數。這個回調用來監聽圖片被捕捉(或者出現了錯誤),而後開發者能夠根據狀況處理結果數據。前面的 takePicture 使用更簡單,但這個 takePicture 提供了更多的靈活性。

camera_view.takePicture(object : 
 ImageCaptureUseCase.OnImageCapturedListener() {
 override fun onCaptureSuccess(
 image: ImageProxy, 
 rotationDegrees: Int
 ) {
 // 處理捕捉的圖片
 }
 override fun onError(
 useCaseError: ImageCaptureUseCase.UseCaseError?, 
 message: String?, 
 cause: Throwable?
 ) {
 // 處理圖片捕獲錯誤
 }
 })
複製代碼

咱們可能也想使用 CameraView 來錄視頻。這時候咱們須要使用 startRecoring() 方法—只須要傳遞一個用來保存結果的文件引用,以及一個 來處理操做結果(成果或者失敗)的 listener

camera_view.startRecording(File("some_file_path"),
 object : VideoCaptureUseCase.OnVideoSavedListener {
 override fun onVideoSaved(file: File?) {
 // Handle video saved
 }
 override fun onError(
 error: VideoCaptureUseCase.UseCaseError?, 
 message: String?, 
 throwable: Throwable?
 ) {
 // Handle video error
 }
 })
複製代碼

這裏你能夠看到,onVideSaved 方法給咱們返回一個被保存的視頻數據的文件實例。咱們也有 onError 方法用來處理錯誤狀態,在咱們的 UI 上根據狀況 做出對應的反饋。當拍攝視頻致使錯誤時,VideoCaptureUseCase.UseCaseError 將會返回下面錯誤狀態中的某一個:

  • UKNOWN_ERROR
  • ENCODER_ERROR
  • MUXER_ERROR
  • RECORDING_IN_PROGRESS

當用戶但願中止拍攝視頻時,咱們只須要調用 stopRecording 方法讓用例 知道咱們但願中止拍攝視頻:

camera_view.stopRecording()
複製代碼

最後,當咱們使用 CameraView 完畢後,咱們必須確保解綁相機,釋放被用到的資源:

override fun onDestroyView() {
 super.onDestroyView()
 CameraX.unbindAll()
}
複製代碼

這篇文章咱們瞭解了 CameraX 庫以及 CameraView,學習如何使用以及使用它可以作什麼。在安卓程序中實現相機功能,尤爲是不須要使用高級的功能,這是一個很大的進步。你將會使用 CameraView 嗎?若是你有任何想分享的想法或者問題,請必定要分享出來!

最後

若是你看到了這裏,以爲文章寫得不錯就給個唄?若是你以爲那裏值得改進的,請給我留言。必定會認真查詢,修正不足。謝謝。

爲何某些人會一直比你優秀,是由於他自己就很優秀還一直在持續努力變得更優秀,而你是否是還在知足於現狀心裏在竊喜!但願讀到這的您能點個小贊關注下我,之後還會更新技術乾貨,謝謝您的支持!

轉發分享+點贊,關注我獲取更多知識點

Android架構師之路很漫長,一塊兒共勉吧!

相關文章
相關標籤/搜索