环境准备:项目配置与依赖引入
这一章,我们来搞定 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 环境配置的依赖关系画成了一张图。你看一眼就知道哪个模块负责什么:
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. 总结几句
环境准备说白了就是三板斧:依赖版本选对、权限声明齐全、混淆规则放过。这章看着简单,但它是后面所有耗时分析的地基。地基没打好,后面楼层越高越容易垮。