使用CameraX幾行代碼實現(xiàn)攝像頭預(yù)覽和拍照

前言

這篇文章只是介紹CameraX的簡單使用,其中包含相機預(yù)覽声怔、拍照剂买、和簡單的圖片偵分析。

參考自官方文檔:https://developer.android.google.cn/training/camerax?hl=zh_CN

本文章Demo代碼:https://github.com/L-X-J/JetpackSample/tree/master/cx

概覽(摘自官方文檔)


CameraX 是一個 Jetpack 支持庫俏拱,旨在幫助您簡化相機應(yīng)用的開發(fā)工作。它提供一致且易于使用的 API 界面吼句,適用于大多數(shù) Android 設(shè)備锅必,并可向后兼容至 Android 5.0(API 級別 21)。

雖然它利用的是 camera2 的功能惕艳,但使用的是更為簡單且基于用例的方法搞隐,該方法具有生命周期感知能力。它還解決了設(shè)備兼容性問題远搪,因此您無需在代碼庫中包含設(shè)備專屬代碼劣纲。這些功能減少了將相機功能添加到應(yīng)用時需要編寫的代碼量。

最后谁鳍,借助 CameraX癞季,開發(fā)者只需兩行代碼就能利用與預(yù)安裝的相機應(yīng)用相同的相機體驗和功能。 CameraX Extensions 是可選插件倘潜,通過該插件绷柒,您可以在支持的設(shè)備上向自己的應(yīng)用中添加人像、HDR涮因、夜間模式和美顏等效果废睦。

引入依賴

    implementation 'androidx.camera:camera-core:1.0.0-alpha06'
    implementation 'androidx.camera:camera-camera2:1.0.0-alpha06'

實現(xiàn)攝像頭預(yù)覽

畫布局

xml布局文件新增一個TextureView且取個id

    <TextureView
        android:id="@+id/view_finder"
        ...
        android:layout_width="380dp"
        android:layout_height="380dp"/>

邏輯代碼實現(xiàn)

在activity中新增兩個方法。

private fun startCamera(){}
private fun updateTransform(){}

因為要實現(xiàn)攝像頭預(yù)覽我們需要動態(tài)獲取權(quán)限(Manifest.permission.CAMERA)养泡。
獲取到權(quán)限后們需要調(diào)用startCamera()函數(shù)嗜湃。如下代碼

class MainActivity : AppCompatActivity() ,LifecycleOwner {
    private lateinit var viewFinder : TextureView
    private val executor = Executors.newSingleThreadExecutor()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewFinder = findViewById(R.id.view_finder)
        //自定義函數(shù)檢查權(quán)限是否擁有
        if (checkAllPermissionsGranted()){
            viewFinder.post { startCamera() }
        }else{
            //如果沒有權(quán)限動態(tài)獲取
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }
        viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
            updateTransform()
        }
    }
}

最后我們實現(xiàn)startCamera()updateTransform()函數(shù)澜掩。

private fun startCamera(){
// 為取景器用例創(chuàng)建配置對象
        val previewConfig = PreviewConfig.Builder().apply {
            setTargetResolution(Size(viewFinder.width,viewFinder.height))
        }.build()

        // 構(gòu)建取景器用例
        val preview = Preview(previewConfig);

        // 每次取景器更新時购披,重新計算布局
        preview.setOnPreviewOutputUpdateListener {
            // 要更新SurfaceTexture,我們必須將其刪除并重新添加
            val parent = viewFinder.parent as ViewGroup
            parent.removeView(viewFinder)
            parent.addView(viewFinder, 0)
            viewFinder.surfaceTexture = it.surfaceTexture
            updateTransform()
        }
        //將用例綁定到生命周期
        CameraX.bindToLifecycle(this, preview)
}
 private fun updateTransform() {
        val matrix = Matrix()

        //計算取景器的中心
        val centerX = viewFinder.width / 2f
        val centerY = viewFinder.height / 2f

        // 糾正預(yù)覽輸出以適應(yīng)顯示旋轉(zhuǎn)
        val rotationDegrees = when(viewFinder.display.rotation) {
            Surface.ROTATION_0 -> 0
            Surface.ROTATION_90 -> 90
            Surface.ROTATION_180 -> 180
            Surface.ROTATION_270 -> 270
            else -> return
        }
        matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)

        // 最后肩榕,將轉(zhuǎn)換應(yīng)用于我們的TextureView
        viewFinder.setTransform(matrix)
    }

這樣我們就實現(xiàn)了攝像頭預(yù)覽刚陡,是不是比之前簡單很多。

拍照

實現(xiàn)拍照功能,我們需要改造一下startCamera()函數(shù)橘荠,同樣還是很少的代碼。

private fun startCamera(){
...
//在 CameraX.bindToLifecycle(this, preview)前添加以下代碼
 // 為圖像捕獲用例創(chuàng)建配置對象
        val imageCaptureConfig = ImageCaptureConfig.Builder().apply {
            // 我們沒有為圖像捕獲設(shè)置分辨率郎逃;相反哥童,我們
            //選擇一個可以推斷出合適的捕獲模式
            // 基于寬高比和請求模式的分辨率
                setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
        }.build()

        // 構(gòu)建圖像捕獲用例并附加按鈕單擊偵聽器
        val imageCapture = ImageCapture(imageCaptureConfig)
        //拍照按鈕
findViewById<ImageButton>(R.id.capture_button).setOnClickListener {
            val file = File(externalMediaDirs.first(),"${System.currentTimeMillis()}.jpg")
            imageCapture.takePicture(file,executor,object : ImageCapture.OnImageSavedListener{
                override fun onImageSaved(file: File) {
                    val msg = "成功: ${file.absolutePath}"
                    Log.d("CameraXApp", msg)
                    viewFinder.post {
                        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                    }
                }

                override fun onError(
                    imageCaptureError: ImageCapture.ImageCaptureError,
                    message: String,
                    cause: Throwable?
                ) {
                    val msg = "失敗: $message"
                    Log.e("CameraXApp", msg, cause)
                    viewFinder.post {
                        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                    }
                 }

            })
        }
        最后綁定一下生命周期
        
       // CameraX.bindToLifecycle(this, preview)//只是預(yù)覽
        CameraX.bindToLifecycle(this, preview,imageCapture)//可以預(yù)覽可以拍照
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市褒翰,隨后出現(xiàn)的幾起案子贮懈,更是在濱河造成了極大的恐慌,老刑警劉巖优训,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朵你,死亡現(xiàn)場離奇詭異,居然都是意外死亡揣非,警方通過查閱死者的電腦和手機抡医,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來早敬,“玉大人忌傻,你說我怎么就攤上這事「慵啵” “怎么了水孩?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琐驴。 經(jīng)常有香客問我俘种,道長,這世上最難降的妖魔是什么绝淡? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任宙刘,我火速辦了婚禮,結(jié)果婚禮上牢酵,老公的妹妹穿的比我還像新娘荐类。我一直安慰自己,他們只是感情好茁帽,可當(dāng)我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布玉罐。 她就那樣靜靜地躺著,像睡著了一般潘拨。 火紅的嫁衣襯著肌膚如雪吊输。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天铁追,我揣著相機與錄音季蚂,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛扭屁,可吹牛的內(nèi)容都是我干的算谈。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼料滥,長吁一口氣:“原來是場噩夢啊……” “哼然眼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起葵腹,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤高每,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后践宴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲸匿,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年阻肩,在試婚紗的時候發(fā)現(xiàn)自己被綠了带欢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡烤惊,死狀恐怖洪囤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撕氧,我是刑警寧澤瘤缩,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站伦泥,受9級特大地震影響剥啤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜不脯,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一府怯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧防楷,春花似錦牺丙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亿昏,卻和暖如春峦剔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背角钩。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工吝沫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呻澜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓惨险,卻偏偏與公主長得像羹幸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辫愉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內(nèi)容