环境准备:项目配置与依赖引入

这一章,我们来搞定 CameraX 的环境搭建。别小看这一步——我见过太多人因为依赖冲突或者版本不匹配,折腾一整天还没跑起来。你想想看,工具链没弄对,后面分析启动耗时全是白搭。

1. 基础项目配置

我建议你直接基于 Android Studio 的 Empty Activity 模板新建一个项目。记得把最低 API 级别拉到 21(Android 5.0),为什么呢?因为 CameraX 从 1.0 版本开始就正式支持 API 21+,低于这个版本你根本用不了。

小经验:我个人习惯把 compileSdk 和 targetSdk 都设为 33 或 34,这样能用到 CameraX 最新的 API 特性,而且兼容性更好。当然,如果你项目本身有特殊限制,保持 32 以上也行。

看一下 project 级别的 build.gradle(注意是 Groovy 语法,Kotlin DSL 也同理):

buildscript {
    ext {
        // 我常用这个版本号,2024年还是稳定的
        camera_version = "1.3.4"
    }
    repositories {
        google()
        mavenCentral()
    }
}

然后切到 app 级别的 build.gradle,添加 CameraX 核心依赖:

dependencies {
    // CameraX core
    implementation "androidx.camera:camera-core:${camera_version}"
    // CameraX Camera2 扩展(最核心的实现)
    implementation "androidx.camera:camera-camera2:${camera_version}"
    // CameraX Lifecycle 绑定(必须)
    implementation "androidx.camera:camera-lifecycle:${camera_version}"
    // CameraX View(PreviewView 等)
    implementation "androidx.camera:camera-view:${camera_version}"
}

为什么是这四个依赖? 简单说:camera-core 提供基础接口,camera-camera2 是实际用 Camera2 API 干活的那个,camera-lifecycle 让你能跟 Activity/Fragment 生命周期无缝绑定,camera-view 给你一个现成的 PreviewView 控件。少了任何一个,你都得自己写一堆胶水代码。

踩过的坑:我曾经在项目里只加了 camera-camera2,结果编译通过但运行时崩溃,报了 ProcessCameraXConfig 找不到。后来才发现 camera-core 是必须的——有些基础类它里面才定义。所以四个依赖一个都不要省。

2. 版本选择:稳定版 vs 预览版

大家可能会纠结:要不要上最新的 1.4.0-alpha 系列?我个人建议:用稳定版。因为我们这个课程是要做启动流程耗时分析,版本波动会引入不确定因素。1.3.x 系列目前是 stable,API 稳定,文档齐全,踩坑的人少。

版本类型 版本号示例 适用场景
稳定版(Stable) 1.3.4 生产环境、性能分析课程
候选版(RC) 1.4.0-rc01 尝鲜、适配新特性
预览版(Alpha) 1.4.0-alpha06 测试新功能、不推荐用于分析

你想想看,如果我们拿到一个 alpha 版本的 CameraX,某个内部实现还没优化好,启动耗时可能会多出几百毫秒,这时候分析出来的结论是假的。所以,咱就用 1.3.4。

3. 混淆规则与架构选择

如果你项目里开了 ProGuard 或 R8,别忘了加上 CameraX 的 keep 规则:

-dontwarn androidx.camera.**
-keep class androidx.camera.** { *; }

嗯,这步很容易被忽略。我曾经给一个客户优化 Camera 启动速度,结果他们 R8 一压缩,把 CameraX 内部的一些回调类给混淆了,运行时直接报 ClassNotFoundException。排查了半天才发现是混淆的锅。

还有 ABI 架构选择:如果你的 App 只支持 armeabi-v7a 和 arm64-v8a,记得在 defaultConfig 里指定:

ndk {
    abiFilters "armeabi-v7a", "arm64-v8a"
}

为什么?CameraX 内部用到了 Camera2 的 native 层,不同的 CPU 架构对应的 libcamera.so 不一样。不写这个,apk 包会变得很大,而且可能在 x86 模拟器上遇到奇怪的问题。我们在真机上分析,只需要 arm 版本就够了。

4. 权限声明:少一个都跑不起来

Camera 权限是必须的。在 AndroidManifest.xml 里加上:

<uses-permission android:name="android.permission.CAMERA" />

<!-- 可选:如果要用前置摄像头做暗光增强(需要 Flash) -->
<uses-permission android:name="android.permission.FLAG_GRANT_WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

注意,从 Android 13(API 33)开始,READ_EXTERNAL_STORAGE 的权限模型变了,但 CameraX 本身不强制要求存储权限。如果你是做录制视频,需要额外的 RECORD_AUDIO 权限。我们这个课程只分析启动流程,不录制,所以只声明 CAMERA 就行。

核心提醒:运行时权限申请不能忘。我们在后面的实战章节会用到 ActivityResultContracts.RequestPermission() 来请求 CAMERA 权限。如果权限没有授予,CameraX 的 ProcessCameraProvider.getInstance() 会直接报错,根本走不到启动流程的日志分析。

5. 项目结构一览

为了让大家有个直观的认识,我把整个 CameraX 环境配置的依赖关系画成了一张图。你看一眼就知道哪个模块负责什么:

CameraX 环境配置依赖关系图 Android 项目(API 21+) build.gradle 配置 混淆规则 (ProGuard) camera-core camera-camera2 camera-lifecycle camera-view 权限声明 (CAMERA) abiFilters (arm) ProcessCameraProvider 初始化可运行 注意:运行时权限申请在代码中完成,但 AndroidManifest.xml 中必须预先声明 CAMERA 权限 否则 ProcessCameraProvider.getInstance() 会抛出 CameraInfoUnavailableException

6. 验证配置是否成功

配置完成后,怎么确认一切就绪?我有个土办法:写一个最简单的 Activity,在 onCreate 里尝试获取 ProcessCameraProvider 实例。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener(Runnable {
            try {
                val provider = cameraProviderFuture.get()
                Log.d("CameraX", "Provider 获取成功: $provider")
            } catch (e: Exception) {
                Log.e("CameraX", "Provider 获取失败", e)
            }
        }, ContextCompat.getMainExecutor(this))
    }
}

如果控制台打印出 Provider 获取成功,那环境就对了。反之,如果是 CameraInfoUnavailableException,大概率是权限没给或者 manifest 中少配了东西。我遇到过最坑的一次是模拟器上跑,结果模拟器不支持 Camera2,报的异常和权限拒绝一模一样——所以建议这个课程所有的分析都在真机上做。

7. 总结几句

环境准备说白了就是三板斧:依赖版本选对、权限声明齐全、混淆规则放过。这章看着简单,但它是后面所有耗时分析的地基。地基没打好,后面楼层越高越容易垮。