Android 音視頻開發(fā)(四) -- CameraX 實現(xiàn)預(yù)覽笋敞、拍照功能

音視頻學(xué)習(xí)demo,正在升級打怪,加油鴨~
Android 音視頻開發(fā)(一) -- 使用AudioRecord 錄制PCM(錄音)荠瘪;AudioTrack播放音頻
Android 音視頻開發(fā)(二) -- Camera1 實現(xiàn)預(yù)覽夯巷、拍照功能
Android 音視頻開發(fā)(三) -- Camera2 實現(xiàn)預(yù)覽、拍照功能
工程:https://github.com/LillteZheng/VideoDemo

一. Camerax 簡介

在前面兩章中哀墓,我們已經(jīng)學(xué)習(xí)了 Camera1 Android 音視頻開發(fā)(二) -- Camera1 實現(xiàn)預(yù)覽趁餐、拍照功能 和 Camera2 Android 音視頻開發(fā)(三) -- Camera2 實現(xiàn)預(yù)覽、拍照功能篮绰,但從上面兩章可以看出來后雷,API 的調(diào)用還是比較繁瑣的,而且像一些最佳尺寸吠各,角度等還得自己算臀突,從 Camera2 的開發(fā)流程就可以知道:

在這里插入圖片描述

真的很難記住這些流程;google 也意識到這個問題贾漏,所以推出了 Camerax 候学,它雖然底層也是利用了 Camera2 的功能,但它的使用卻更加簡潔纵散,它的主要優(yōu)勢如下:

  1. 更加簡潔的 API 調(diào)用盒齿,基本十幾行代碼就能實現(xiàn)預(yù)覽
  2. Camerax 為 Jetpack 的支持庫,所以也具備感知生命周期的功能困食,即你無需自己釋放 生命周期
  3. 更好兼容性
  4. 更多功能边翁,比如圖片分析等

注意,Camerax 也只支持 API21 及以上硕盹,本次效果如下:

GIF.gif

二. Camerax 使用說明

Camerax 的使用非常簡單符匾,首先,添加關(guān)聯(lián)庫

def camerax_version = "1.0.0-beta06"
// CameraX 核心庫
implementation "androidx.camera:camera-camera2:$camerax_version"
// CameraX 生命周期
implementation "androidx.camera:camera-lifecycle:$camerax_version"
// CameraX view 集合瘩例,比如 cameraview啊胶,preview等
implementation "androidx.camera:camera-view:1.0.0-alpha10"

權(quán)限

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

2.1 預(yù)覽

首先,先通過

  ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

返回當(dāng)前可以綁定生命周期的 ProcessCameraProvider垛贤,ProcessCameraProvider 它會和宿主綁定生命周期焰坪,這樣就不用擔(dān)心打開相機(jī)和關(guān)閉的問題了。

接著聘惦,向 cameraProviderFuture 注冊一個監(jiān)聽某饰,第一個參數(shù)是一個 runnable,第二個參數(shù)是線程池,即runnable 運(yùn)行在哪個線程中:

cameraProviderFuture.addListener(Runnable {}, ContextCompat.getMainExecutor(this))

上面我們讓它運(yùn)行在主線程的線程池中黔漂,這樣诫尽,在這個 runnable 中,就可以配置我們的 capture 了:

        //創(chuàng)建相機(jī)進(jìn)程監(jiān)聽
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(new Runnable() {
            @SuppressLint("RestrictedApi")
            @Override
            public void run() {
                try {
                    //將相機(jī)的生命周期和activity的生命周期綁定炬守,camerax 會自己釋放牧嫉,不用擔(dān)心了
                    ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                    //預(yù)覽的 capture,它里面支持角度換算
                    Preview preview = new Preview.Builder().build();

                    //創(chuàng)建圖片的 capture
                    mImageCapture = new ImageCapture.Builder()
                            .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
                            .build();

                   
                    //選擇后置攝像頭
                    CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();

                    //預(yù)覽之前先解綁
                    cameraProvider.unbindAll();

                    //將數(shù)據(jù)綁定到相機(jī)的生命周期中
                    Camera camera = cameraProvider.bindToLifecycle(CameraxActivity.this, cameraSelector, preview, mImageCapture);
                    //將previewview 的 surface 給相機(jī)預(yù)覽
                    preview.setSurfaceProvider(mViewFinder.createSurfaceProvider(camera.getCameraInfo()));

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },ContextCompat.getMainExecutor(this));

可以看到减途,使用 ProcessCameraProvider.getInstance(this) 獲取當(dāng)前的 ProcessCameraProvider 去監(jiān)聽宿主的生命周期酣藻。

創(chuàng)建并確認(rèn) CameraProvider 后,執(zhí)行步驟如下

  1. 創(chuàng)建 Preview鳍置,使用 new Preview.Builder().build() 創(chuàng)建Preview臊恋,它是相機(jī)預(yù)覽的數(shù)據(jù)流,圖像數(shù)據(jù)會通過它來輸出墓捻,比如輸出到 Surface 中
  2. 創(chuàng)建 ImageCapture 用于拍照抖仅,這里的 builder 都可以設(shè)置參數(shù),比如大小砖第,曝光等
  3. 指定所需的相機(jī) LensFacing 選項撤卢,這里直接使用后置即可
  4. 將所選相機(jī)和任意用例綁定到生命周期,通過 cameraProvider.bindToLifecycle梧兼,將宿主的生命周期放吩,與 cameraSelector,preview和mImageCapture判定起來羽杰。
  5. 將 Preview 連接到 PreviewView渡紫,preview.setSurfaceProvider() 設(shè)置要預(yù)覽的 surface

上面的的 mViewFinder 其實是一個 PreviewView ,這是一種可以剪裁考赛、縮放和旋轉(zhuǎn)以確保正確顯示的 View惕澎,即不用你自己去設(shè)置預(yù)覽的角度等問題了。

    <androidx.camera.view.PreviewView
        android:id="@+id/viewFinder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

2.2. 拍照

上面已經(jīng)設(shè)置了 mImageCapture颜骤,拍照呢唧喉,在 Camerax 中也很簡單,使用 takePicture 即可忍抽,如下

 public void takePhoto(View view) {
        if (mImageCapture != null) {
            File dir = new File(Constants.PATH);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            //創(chuàng)建文件
            File file = new File(Constants.PATH,"testx.jpg");
            if (file.exists()) {
                file.delete();
            }
            //創(chuàng)建包文件的數(shù)據(jù)八孝,比如創(chuàng)建文件
            ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();

            //開始拍照
            mImageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
                @Override
                public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                //    Uri savedUri = outputFileResults.getSavedUri();
                    Toast.makeText(CameraxActivity.this, "保存成功: ", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(@NonNull ImageCaptureException exception) {
                    Toast.makeText(CameraxActivity.this, "保存失敗", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

注釋已經(jīng)很清楚了,注意我們可以使用 ImageCapture.OutputFileOptions 讓 Camerax 去幫我們保存圖片文件鸠项。

參考:
https://codelabs.developers.google.com/codelabs/camerax-getting-started/#0

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末干跛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子祟绊,更是在濱河造成了極大的恐慌楼入,老刑警劉巖哥捕,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浅辙,居然都是意外死亡扭弧,警方通過查閱死者的電腦和手機(jī)阎姥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門记舆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人呼巴,你說我怎么就攤上這事泽腮。” “怎么了衣赶?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵诊赊,是天一觀的道長。 經(jīng)常有香客問我府瞄,道長碧磅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任遵馆,我火速辦了婚禮鲸郊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘货邓。我一直安慰自己秆撮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布换况。 她就那樣靜靜地躺著职辨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戈二。 梳的紋絲不亂的頭發(fā)上舒裤,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音觉吭,去河邊找鬼惭每。 笑死,一個胖子當(dāng)著我的面吹牛亏栈,可吹牛的內(nèi)容都是我干的台腥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼绒北,長吁一口氣:“原來是場噩夢啊……” “哼黎侈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起闷游,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤峻汉,失蹤者是張志新(化名)和其女友劉穎贴汪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體休吠,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扳埂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瘤礁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阳懂。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柜思,靈堂內(nèi)的尸體忽然破棺而出岩调,到底是詐尸還是另有隱情,我是刑警寧澤赡盘,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布号枕,位于F島的核電站,受9級特大地震影響陨享,放射性物質(zhì)發(fā)生泄漏葱淳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一抛姑、第九天 我趴在偏房一處隱蔽的房頂上張望赞厕。 院中可真熱鬧,春花似錦途戒、人聲如沸坑傅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唁毒。三九已至,卻和暖如春星爪,著一層夾襖步出監(jiān)牢的瞬間浆西,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工顽腾, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留近零,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓抄肖,卻偏偏與公主長得像久信,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漓摩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359