0 引言
CameraX 是一个 Jetpack 库,旨在帮助开发者更轻松地开发相机应用。它提供了一个一致且易于使用的 API,该 API 适用于绝大多数 Android 设备,并向后兼容 Android 5.0(API 级别 21)。
与之对应的是Camera2,它是低级别 Android 相机软件包,用于替代已废弃的 Camera 类。Camera2 可为复杂的用例提供深入的控制功能,但要求您管理设备专属配置。
CameraX 从几个主要方面改善了开发者体验。
- 广泛的设备兼容性:CameraX 支持搭载 Android 5.0(API 级别 21)或更高版本的设备,覆盖现有 Android 设备的 98% 以上。
- 易用性:CameraX 着重于用例,使开发者可以专注于需要完成的任务,而无需花时间处理不同设备之间的细微差别。CameraX 支持大多数常见的相机用例:预览、图片分析、图片拍摄和视频拍摄。
- 确保各设备间的一致性:要维持一致的相机行为并非易事。开发者必须考虑宽高比、屏幕方向、旋转角度、预览大小和图像大小。有了 CameraX,这些基本行为都不用再费心。
1 创建项目与依赖配置
首先创建一个Empty Views Activity项目:
开发语言这里选择Java,构建配置语言选择Groovy:
接着app模块的build.gradle文件中添加Gradle依赖项:
dependencies {
def camerax_version = "1.3.0-alpha04"
implementation "androidx.camera:camera-core:$camerax_version"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-video:$camerax_version"
implementation "androidx.camera:camera-view:$camerax_version"
implementation "androidx.camera:camera-extensions:$camerax_version"
}
应用需要获得用户授权才能打开相机,因此打开 AndroidManifest.xml,然后将以下代码行添加到 application 标记之前:
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
最后修改布局文件activity_main.xml,加入相机预览视图androidx.camera.view.PreviewView:
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
让PreviewView占满整个布局界面。这样整个项目的整体框架就搭建好了,接下来就是代码层面的内容了。
2 声明成员变量
在一个使用CameraX实现的简单的相机实时预览项目中,主要需要定义三个重要的成员变量:ListenableFuture、PreviewView和CameraSelector。代码如下:
private ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;
private PreviewView previewView;
private CameraSelector cameraSelector;
ProcessCameraProvider 是 CameraX 的核心类,用于绑定和管理相机的生命周期。
ListenableFuture 是一个异步任务的接口,用于获取 ProcessCameraProvider 的实例。
它是 Guava 库 中的类,支持回调机制,可以监听任务完成的状态。
PreviewView 是 CameraX 提供的 UI 组件,用于显示相机的实时预览。它继承自 FrameLayout,可以方便地添加到布局中,支持调整显示方式(如裁剪、拉伸)。
CameraSelector 用于选择相机的前后摄像头(或其他特定摄像头)。它是 CameraX 提供的一个工具类,提供了便捷的选择器。
2 请求相机权限
在程序中,我们要先判断App是否有相机权限,如果有则开始打开相机。
// App拥有所需权限才打开相机,否则请求相机权限
if (allPermissionsGranted()) {
startCamera();
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}
// 遍历所需权限数组REQUIRED_PERMISSIONS
private boolean allPermissionsGranted() {
for (String permission : REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true
}
// 监听权限请求结果,权限获取到后继续调用startCamera()函数
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera();
}
}
}
3 通过 CameraX 实现相机预览绑定
启动CameraX
private void startCamera() {
// 获取 ProcessCameraProvider 的异步实例
processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this);
// 通过 `ListenableFuture` 的监听器在实例可用时执行绑定相机操作
processCameraProviderListenableFuture.addListener(() -> {
try {
ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get();
bindCamera(processCameraProvider);
} catch (Exception e) {
throw new RuntimeException(e);
}
}, ContextCompat.getMainExecutor(this));
}
绑定相机到生命周期
private void bindCamera(ProcessCameraProvider processCameraProvider) {
// 调用 `unbindAll()` 释放之前绑定的所有相机资源,确保不会出现重复绑定
processCameraProvider.unbindAll();
// 使用 `CameraSelector` 指定相机镜头
cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
// 配置 `Preview` 并将其与 `PreviewView` 的 `SurfaceProvider` 绑定
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
// 通过 `bindToLifecycle()` 方法,将相机绑定到当前 Activity 的生命周期
processCameraProvider.bindToLifecycle(this, cameraSelector, preview);
}
4 结果与总结
通过本篇博客,我们详细讲解了如何快速使用 CameraX 实现相机实时预览的完整流程。从项目初始化、权限配置到相机启动与绑定,每一步都展示了清晰的代码示例与实现思路,帮助开发者快速上手 CameraX 的核心功能。