0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在Jetpack Compose中解锁CameraX的强大功能

谷歌开发者 ? 来源:Android 开发者 ? 2025-02-25 11:50 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

作者 / Google 开发者关系工程师 Jolanda Verhoef

本文是 "相机与媒体 Spotlight Week" 系列的内容之一。此系列中,我们会提供文章、视频、示例代码等资源,以帮助您提升应用中的媒体体验。

我们了解到您喜欢 CameraX 和 Jetpack Compose 库提供的强大功能,但希望使用更符合语言习惯的 Compose API 来构建相机界面。今年,我们的工程团队开发了两个新的 Compose 工件,即低层级 viewfinder-compose 和高层级 camera-compose。两者现在均已推出 alpha 版本 。

在本系列文章中,我们不仅将为您介绍如何将 camera-compose API 集成到应用中,还将向您展示与 Compose 集成所带来的一些令人愉悦的界面体验。所有令人赞叹的 Compose 功能 (例如自适应 API 和动画支持) 均已与相机预览无缝集成。

完成所有这些操作后,我们的最终应用将如下所示:

此外,应用可以顺畅地在桌面模式之间切换:

到本文 (该系列第一篇文章) 的末尾,您将构建一个功能齐全的相机取景器,并将在后续系列文章中对其进行扩展。欢迎您跟随我们一起编写代码,在实践中更好地学习。

添加库依赖项

假设您已经在应用中设置了 Compose。如果您想继续,只需在 Android Studio 中新建一个应用即可。我们通常使用最新的 Canary 版本,因为这个版本会提供最新的 Compose 模板。
向您的 libs.versions.toml 中添加以下内容:

[versions]
..
camerax = "1.5.0-alpha03"
accompanist = "0.36.0" # or whatever matches with your Compose version


[libraries]
..
# Contains the basic camera functionality such as SurfaceRequest
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }
# Contains the CameraXViewfinder composable
androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }
# Allows us to bind the camera preview to our UI lifecycle
androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }
# The specific camera implementation that renders the preview
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }
# The helper library to grant the camera permission
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
然后,将这些添加到您的模块 build.gradle.kts 依赖项块中:
dependencies {
  ..
  implementation(libs.androidx.camera.core)
  implementation(libs.androidx.camera.compose)
  implementation(libs.androidx.camera.lifecycle)
  implementation(libs.androidx.camera.camera2)
  implementation(libs.accompanist.permissions)
}
?
为了授予相机权限,我们添加了所有依赖项,然后实际显示相机预览。接下来,让我们看看如何授予正确的权限。

授予相机权限

通过使用 Accompanist 权限库,我们可以轻松地授予正确的相机权限。首先,我们需要设置 AndroidManifest.xml:


    
    


    ..


Accompanist 权限库

https://google.github.io/accompanist/permissions/

现在,我们只需按照库的说明授予正确的权限:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyApplicationTheme {
                CameraPreviewScreen()
            }
        }
    }
}


@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun CameraPreviewScreen(modifier: Modifier = Modifier) {
    val cameraPermissionState = rememberPermissionState(android.Manifest.permission.CAMERA)
    if (cameraPermissionState.status.isGranted) {
        CameraPreviewContent(modifier)
    } else {
        Column(
            modifier = modifier.fillMaxSize().wrapContentSize().widthIn(max = 480.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            val textToShow = if (cameraPermissionState.status.shouldShowRationale) {
                // If the user has denied the permission but the rationale can be shown,
                // then gently explain why the app requires this permission
                "Whoops! Looks like we need your camera to work our magic!" +
                    "Don't worry, we just wanna see your pretty face (and maybe some cats).  " +
                    "Grant us permission and let's get this party started!"
            } else {
                // If it's the first time the user lands on this feature, or the user
                // doesn't want to be asked again for this permission, explain that the
                // permission is required
                "Hi there! We need your camera to work our magic! 
" +
                    "Grant us permission and let's get this party started! uD83CuDF89"
            }
            Text(textToShow, textAlign = TextAlign.Center)
            Spacer(Modifier.height(16.dp))
            Button(onClick = { cameraPermissionState.launchPermissionRequest() }) {
                Text("Unleash the Camera!")
            }
        }
    }
}


@Composable
private fun CameraPreviewContent(modifier: Modifier = Modifier) {
    // TODO: Implement
}
这样,我们就得到了一个良好的界面,用户可以在显示相机预览之前授予相机权限:

创建 ViewModel

将业务逻辑与界面分开是一种很好的实践。为此,我们可以为屏幕创建视图模型来实现这一点。这个视图模型设置了 CameraX Preview 用例。请注意,CameraX 中的用例代表了可以使用该库实现的各种工作流程的配置,即预览、捕获、录制和分析。视图模型还将界面绑定到相机提供程序:

class CameraPreviewViewModel : ViewModel() {
    // Used to set up a link between the Camera and your UI.
    private val _surfaceRequest = MutableStateFlow(null)
    val surfaceRequest: StateFlow = _surfaceRequest


    private val cameraPreviewUseCase = Preview.Builder().build().apply {
        setSurfaceProvider { newSurfaceRequest ->
            _surfaceRequest.update { newSurfaceRequest }
        }
    }


    suspend fun bindToCamera(appContext: Context, lifecycleOwner: LifecycleOwner) {
        val processCameraProvider = ProcessCameraProvider.awaitInstance(appContext)
        processCameraProvider.bindToLifecycle(
            lifecycleOwner, DEFAULT_FRONT_CAMERA, cameraPreviewUseCase
        )


        // Cancellation signals we're done with the camera
        try { awaitCancellation() } finally { processCameraProvider.unbindAll() }
    }
}

此处会执行大量操作。代码定义了一个 CameraPreviewViewModel 类,负责管理相机预览。此类使用 CameraX Preview 构建器来配置预览与界面的绑定方式。bindToCamera 函数用于初始化相机,并将其绑定到指定的 LifecycleOwner,以确保相机至少在生命周期处于 "启动" 状态时运行,并启动预览流。
相机作为相机库的内部组件,需要渲染到界面提供的 surface。因此,库需要有一种方法来请求 surface。这正是 SurfaceRequest 的用途。因此,每当相机表示需要 surface 时,就会触发 surfaceRequest。然后将该请求转发给界面,以便将 surface 传递给请求对象。

最后,我们需要等待界面与相机完成绑定,并确保释放相机资源以避免资源泄漏。

实现相机预览界面

现在我们有了一个视图模型,可以实现 CameraPreviewContent 可组合项。该项从视图模型中读取 surface 请求,在可组合项位于组合树中时绑定到相机,并从库中调用 CameraXViewfinder。

@Composable
fun CameraPreviewContent(
    viewModel: CameraPreviewViewModel,
    modifier: Modifier = Modifier,
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
) {
    val surfaceRequest by viewModel.surfaceRequest.collectAsStateWithLifecycle()
    val context = LocalContext.current
    LaunchedEffect(lifecycleOwner) { 
        viewModel.bindToCamera(context.applicationContext, lifecycleOwner) 
    }


    surfaceRequest?.let { request ->
        CameraXViewfinder(
            surfaceRequest = request,
            modifier = modifier
        )
    }
}


如上部分所述,surfaceRequest 允许相机库在需要渲染时请求一个 surface。在这段代码中,我们收集这些 surfaceRequest 实例,并将它们转发给属于 camera-compose 组件的 CameraXViewfinder。

结果

就这样,我们构建了一个功能齐全的全屏取景器。了解完整代码片段,请访问相关文档:


https://gist.github.com/JolandaVerhoef/74d4696b804736c698450bd34b5c9ff8

本文中的代码段包含以下许可证:

// Copyright 2024 Google LLC. SPDX-License-Identifier: Apache-2.0

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Google
    +关注

    关注

    5

    文章

    1791

    浏览量

    59147
  • 相机
    +关注

    关注

    4

    文章

    1479

    浏览量

    54757
  • API
    API
    +关注

    关注

    2

    文章

    1661

    浏览量

    64217

原文标题:在 Jetpack Compose 中解锁 CameraX 的强大功能

文章出处:【微信号:Google_Developers,微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    compose的使用技巧是什么?

    compose的使用技巧是什么?
    发表于 11-15 07:27

    深入了解CameraX 1.1版本的视频拍摄功能

      CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供一致且易用的 API 接口,适用于大多数 Android 设备,并可向后兼容至 Android 5.0 (API 级别 21)。我们将在本文中介绍
    的头像 发表于 01-25 12:01 ?3647次阅读

    详解Jetpack Compose 1.1版本的新功能

    我们一如既往地搭建产品路线图,现在已经发布了 Jetpack Compose 的 1.1 版本,这是 Android 的现代原生界面工具包。此版本新增了一些功能,比如经过优化的焦点处理、触摸目标值
    的头像 发表于 03-11 10:14 ?1698次阅读

    Jetpack Compose基础知识科普

    Jetpack Compose 是用于构建原生 Android 界面的新工具包。它可简化并加快 Android 上的界面开发,使用更少的代码、强大的工具和直观的 Kotlin API,快速让应用生动
    的头像 发表于 04-02 13:38 ?3420次阅读

    Compose社区的反响

    我们很高兴地看到这些团队大规模和复杂的生产环境仔细地评估并使用了 Compose,所带来的结果也不仅是让界面开发更清晰有趣,也带来了更多工程上的收益。这只是其中几个案例,因为 Play 商店排名前 1,000 的应用中有超过
    的头像 发表于 05-18 10:15 ?1321次阅读

    Jetpack Compose 更新一览 | 2022 Android 开发者峰会

    作者 /?Android 开发者关系工程师 Jolanda Verhoef 去年我们发布了 Jetpack Compose ,此后一直进行优化。我们已添加了新的功能并创造出
    的头像 发表于 11-23 17:55 ?1535次阅读

    Google计划用Jetpack Compose来重建Android系统的设置应用

    上周,Google 发布了 Android 14 的首个开发者预览版,除了那些最新的功能以外,Google 似乎还正在默默酝酿一个新的计划 —— 用更现代的 Jetpack Compose 来逐步
    的头像 发表于 02-18 11:16 ?1913次阅读

    Compose for Wear OS 1.1 推出稳定版: 了解新功能

    为 Wear OS 构建出色的响应式应用。 ? Compose for Wear OS?1.1 版本 https://developer.android.google.cn/jetpack
    的头像 发表于 02-22 01:30 ?1292次阅读

    Kotlin声明式UI框架Compose Multiplatform支持iOS

    JetBrains ?KotlinConf’23 大会上宣布,Compose Multiplatform 已支持 iOS,目前处于 alpha 阶段。至此,Compose
    的头像 发表于 04-24 09:12 ?1723次阅读
    Kotlin声明式UI框架<b class='flag-5'>Compose</b> Multiplatform支持iOS

    I/O 看未来 | Jetpack功能一览

    应用构建特色功能。Google Play 上的大多数应用都使用 Jetpack 进行开发,事实上, 排行榜前 1,000 的应用,超过 90% 的应用都使用了
    的头像 发表于 06-01 01:20 ?639次阅读
    <b class='flag-5'>在</b> I/O 看未来 | <b class='flag-5'>Jetpack</b> 新<b class='flag-5'>功能</b>一览

    Jetpack WindowManager 1.1 稳定版

    变化。许多新款设备都已进入市场,大量新用例也已解锁Jetpack WindowManager 库在帮助您优化您的 Android 应用上发挥重要作用,使其能够适用于不同的设备类型。并且此版本还包含多项
    的头像 发表于 10-18 19:10 ?714次阅读
    <b class='flag-5'>Jetpack</b> WindowManager 1.1 稳定版

    Jetpack Compose和设备类型的三大重要更新

    2024 年 Google I/O 大会上我们分享了大量更新和公告,帮助开发者提升工作效率。了解 2024 年 Google I/O 大会上有关 Jetpack Compose 和设备类型的三大重要更新。
    的头像 发表于 08-09 17:07 ?1040次阅读

    NVIDIA JetPack 6.0版本的关键功能

    NVIDIA JetPack SDK 支持 NVIDIA Jetson 模块,为构建端到端加速 AI 应用提供全面的解决方案。JetPack 6 通过微服务和一系列新功能,扩展了 Jetson 平台的灵活性和可扩展性,是 202
    的头像 发表于 09-09 10:18 ?1143次阅读
    NVIDIA <b class='flag-5'>JetPack</b> 6.0版本的关键<b class='flag-5'>功能</b>

    解析NVIDIA JetPack 6.1的新功能

    NVIDIA JetPack一直不断发展,通过提供量身定制的先进软件满足边缘 AI 和机器人开发者日益增长的需求。每次发布的 JetPack 新版本都会升级性能、加入新功能与优化现有
    的头像 发表于 11-28 10:41 ?1111次阅读
    解析NVIDIA <b class='flag-5'>JetPack</b> 6.1的新<b class='flag-5'>功能</b>

    详解Jetpack Compose布局流程

    我们与 Android 经典视图系统的生命周期 (Measure,Layout,Drawing) 做一个对比: 组合是 Compose 的特有阶段,是其能够通过函数调用实现声明式 UI 的核心,想要深入理解 Compose 第一课就是理解这个过程。
    的头像 发表于 02-05 13:38 ?772次阅读
    详解<b class='flag-5'>Jetpack</b> <b class='flag-5'>Compose</b>布局流程