当前位置: 首页 > news >正文

在 Jetpack Compose 中使用 CameraX示例

在使用Jetpack Compose开发安卓应用,当在学习使用CameraX组件时发现官方提供的教程不是Compose的。教程地址如下:
https://developer.android.com/codelabs/camerax-getting-started?hl=zh-cn#1
与是我就记录一下,简单的示例。

内容参考:
https://medium.com/@deepugeorge2007travel/mastering-camerax-in-jetpack-compose-a-comprehensive-guide-for-android-developers-92ec3591a189
在这里插入图片描述

依赖

build.gradle中增加以下内容:

dependencies {// Camerax implementationdef cameraxVersion = "1.3.1"implementation ("androidx.camera:camera-core:${cameraxVersion}")implementation ("androidx.camera:camera-camera2:${cameraxVersion}")implementation ("androidx.camera:camera-view:${cameraxVersion}")implementation ("androidx.camera:camera-lifecycle:$cameraxVersion")// Camerax implementation
}

权限

修改文件CmrXTutorial/app/src/main/AndroidManifest.xml
增加以下内容:

<uses-featureandroid:name="android.hardware.camera"android:required="false" />
<uses-permission android:name="android.permission.CAMERA"/>

修改完以后形如:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><uses-featureandroid:name="android.hardware.camera"android:required="false" /><uses-permission android:name="android.permission.CAMERA"/><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"...略...</application>
</manifest>

cmrxtutorial/composables/Camerax.kt

代码如下:

package com.android.example.cmrxtutorial.composablesimport android.content.ContentValues
import android.content.Context
import android.os.Build
import android.provider.MediaStore
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine@Composable
fun CameraPreviewScreen() {val lensFacing = CameraSelector.LENS_FACING_BACKval lifecycleOwner = LocalLifecycleOwner.currentval context = LocalContext.currentval preview = Preview.Builder().build()val previewView = remember {PreviewView(context)}val cameraxSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()val imageCapture = remember {ImageCapture.Builder().build()}LaunchedEffect(lensFacing) {val cameraProvider = context.getCameraProvider()cameraProvider.unbindAll()cameraProvider.bindToLifecycle(lifecycleOwner, cameraxSelector, preview, imageCapture)preview.setSurfaceProvider(previewView.surfaceProvider)}Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.fillMaxSize()) {AndroidView({ previewView }, modifier = Modifier.fillMaxSize())Button(onClick = { captureImage(imageCapture, context) }) {Text(text = "Capture Image")}}
}private fun captureImage(imageCapture: ImageCapture, context: Context) {val name = "CameraxImage.jpeg"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")}}val outputOptions = ImageCapture.OutputFileOptions.Builder(context.contentResolver,MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues).build()imageCapture.takePicture(outputOptions,ContextCompat.getMainExecutor(context),object : ImageCapture.OnImageSavedCallback {override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {println("Successs")}override fun onError(exception: ImageCaptureException) {println("Failed $exception")}})
}private suspend fun Context.getCameraProvider(): ProcessCameraProvider =suspendCoroutine { continuation ->ProcessCameraProvider.getInstance(this).also { cameraProvider ->cameraProvider.addListener({continuation.resume(cameraProvider.get())}, ContextCompat.getMainExecutor(this))}}

cmrxtutorial/MainActivity.kt

代码如下:

package com.android.example.cmrxtutorialimport android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.content.ContextCompat
import com.android.example.cmrxtutorial.composables.CameraPreviewScreen
import com.android.example.cmrxtutorial.ui.theme.CmrXTutorialThemeclass MainActivity : ComponentActivity() {private val cameraPermissionRequest =registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->if (isGranted) {setCameraPreview()} else {// Camera permission denied}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)when (PackageManager.PERMISSION_GRANTED) {ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA) -> {setCameraPreview()}else -> {cameraPermissionRequest.launch(Manifest.permission.CAMERA)}}}private fun setCameraPreview() {setContent {CmrXTutorialTheme {// A surface container using the 'background' color from the themeSurface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {CameraPreviewScreen()}}}}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis核心技术与实战学习笔记
  • 追问试面试系列:线程池
  • 【区块链+绿色低碳】泸州:“绿芽积分”号召全民绿色减碳 | FISCO BCOS应用案例
  • 前端构建工具Vite
  • 【React】useState:状态更新规则详解
  • Linux运维高频用途脚本和命令行,持续更新......
  • Hutool中SpringUtil中的一个坑-所有路由消失
  • docker安装elasticsearch(es)最新版本
  • 3.5.3、查找和排序算法-插入类排序和选择类排序
  • Dify中语音和文字间转换问题的一种暂时注释方式
  • 大模型算法面试题(十七)
  • Django实战:开启数字化任务管理的新纪元
  • C/C++编程-算法学习-数字滤波器
  • 日常踩坑---ljmp在BIOS中的使用
  • pytest-html报告修改与汉化
  • [deviceone开发]-do_Webview的基本示例
  • 【React系列】如何构建React应用程序
  • Javascript弹出层-初探
  • js面向对象
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • SQLServer插入数据
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • windows下mongoDB的环境配置
  • 猴子数据域名防封接口降低小说被封的风险
  • 机器学习学习笔记一
  • 配置 PM2 实现代码自动发布
  • 前端攻城师
  • 前端学习笔记之观察者模式
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 实习面试笔记
  • 实现菜单下拉伸展折叠效果demo
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 我是如何设计 Upload 上传组件的
  • 学习JavaScript数据结构与算法 — 树
  • 优秀架构师必须掌握的架构思维
  • 在Unity中实现一个简单的消息管理器
  • 自制字幕遮挡器
  • elasticsearch-head插件安装
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​比特币大跌的 2 个原因
  • ​马来语翻译中文去哪比较好?
  • # Java NIO(一)FileChannel
  • #HarmonyOS:Web组件的使用
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • (04)odoo视图操作
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第6节 (嵌套的Finally代码块)
  • (第61天)多租户架构(CDB/PDB)
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式