1. Camera2 API 架构解析
Camera2 API 是 Android 5.0 (Lollipop) 引入的全新相机框架,它彻底重构了 Android 相机系统的工作方式。与旧版 Camera API 相比,Camera2 采用了更加模块化和灵活的架构设计。
1.1 核心组件层级
Camera2 架构自上而下分为四个主要层级:
- 应用层:开发者直接交互的 API 接口
- 框架层:Android 系统提供的相机服务
- HAL3 层:硬件抽象层实现
- 硬件层:物理相机设备
这种分层设计使得 Camera2 能够更好地适应不同厂商的硬件实现,同时为开发者提供一致的编程接口。
1.2 关键类与职责
Camera2 API 的核心类构成了开发者与相机系统交互的主要接口:
| 类名 | 职责 | 典型使用场景 |
|---|---|---|
| CameraManager | 相机系统入口点,枚举可用相机设备 | 获取相机列表,打开指定相机 |
| CameraDevice | 表示单个相机硬件实例 | 配置相机参数,创建会话 |
| CameraCaptureSession | 管理相机数据流和捕获请求 | 处理预览和拍照请求 |
| CaptureRequest | 定义单次捕获的参数配置 | 设置对焦模式、曝光补偿等 |
| CaptureResult | 提供捕获操作的元数据结果 | 获取实际使用的曝光值、对焦状态等 |
提示:在实际开发中,CameraDevice 和 CameraCaptureSession 的生命周期管理尤为重要,不当处理可能导致资源泄漏或相机服务崩溃。
2. 基础开发流程实战
2.1 相机初始化与权限处理
完整的相机初始化流程包含以下几个关键步骤:
- 权限检查:必须确保应用已获得 CAMERA 权限
- 相机特性查询:通过 CameraCharacteristics 获取设备能力
- 相机打开:异步操作,需正确处理回调
典型实现代码如下:
java复制private void openCamera() {
// 检查权限
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// 处理权限请求
return;
}
try {
// 获取相机管理器
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
// 选择后置相机
String cameraId = getBackCameraId(manager);
// 异步打开相机
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
// 相机已就绪,保存引用
this.cameraDevice = camera;
// 创建预览会话
createPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
// 处理相机断开
camera.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
// 处理错误
camera.close();
}
}, null);
} catch (CameraAccessException e) {
// 处理相机访问异常
}
}
2.2 预览会话创建
预览是相机应用的基础功能,创建预览会话需要注意以下几点:
- Surface准备:通常使用 TextureView 或 SurfaceView 的 Surface
- 分辨率选择:应选择设备支持且适合显示的分辨率
- 请求模板:使用 TEMPLATE_PREVIEW 模板
优化后的预览会话创建代码:
java复制private void createPreviewSession() {
try {
// 准备预览Surface
SurfaceTexture texture = textureView.getSurfaceTexture();
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface previewSurface = new Surface(texture);
// 创建捕获请求构建器
previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(previewSurface);
// 配置自动对焦和曝光
configureAutoFocus(previewRequestBuilder);
// 创建捕获会话
cameraDevice.createCaptureSession(
Arrays.asList(previewSurface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
// 会话就绪,开始预览
try {
session.setRepeatingRequest(
previewRequestBuilder.build(),
null, null);
} catch (CameraAccessException e) {
// 处理异常
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
// 处理配置失败
}
},
null);
} catch (CameraAccessException e) {
// 处理异常
}
}
3. 高级功能实现
3.1 手动控制实现
Camera2 的强大之处在于提供了精细的手动控制能力:
手动对焦实现
java复制public void manualFocus(float x, float y) {
// 计算对焦区域
Rect focusArea = calculateFocusArea(x, y);
// 配置对焦区域
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS,
new MeteringRectangle[]{new MeteringRectangle(focusArea, 1000)});
// 触发对焦
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_TRIGGER_START);
try {
captureSession.capture(previewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
// 处理异常
}
}
手动曝光控制
java复制public void setManualExposure(long exposureTime, int iso) {
// 检查设备是否支持手动曝光
if (!isManualExposureSupported()) {
return;
}
// 设置手动模式
previewRequestBuilder.set(CaptureRequest.CONTROL_MODE,
CameraMetadata.CONTROL_MODE_OFF);
// 配置曝光时间
previewRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposureTime);
// 配置ISO感光度
previewRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, iso);
// 应用设置
updatePreview();
}
3.2 RAW格式拍摄
RAW格式拍摄可以获取未经处理的传感器数据,为后期处理提供更大空间:
java复制public void captureRaw() {
// 创建RAW格式的ImageReader
ImageReader rawReader = ImageReader.newInstance(
rawSize.getWidth(), rawSize.getHeight(),
ImageFormat.RAW_SENSOR, 2);
rawReader.setOnImageAvailableListener(reader -> {
Image image = reader.acquireNextImage();
// 处理RAW数据
processRawImage(image);
image.close();
}, null);
// 创建捕获请求
CaptureRequest.Builder rawBuilder = cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
rawBuilder.addTarget(rawReader.getSurface());
// 禁用自动处理
rawBuilder.set(CaptureRequest.CONTROL_MODE,
CameraMetadata.CONTROL_MODE_OFF);
// 执行捕获
try {
captureSession.capture(rawBuilder.build(), null, null);
} catch (CameraAccessException e) {
// 处理异常
}
}
4. 性能优化技巧
4.1 相机能力查询优化
合理利用相机特性可以显著提升应用性能:
java复制public void printCameraCapabilities(String cameraId) {
CameraCharacteristics characteristics =
cameraManager.getCameraCharacteristics(cameraId);
// 获取支持的分辨率
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] jpegSizes = map.getOutputSizes(ImageFormat.JPEG);
// 获取对焦能力
int[] afModes = characteristics.get(
CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
// 获取曝光范围
Range<Long> exposureRange = characteristics.get(
CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
// 打印信息...
}
4.2 连拍模式实现
高效连拍需要注意内存管理和请求队列优化:
java复制public void captureBurst(int count) {
List<CaptureRequest> requests = new ArrayList<>();
// 准备多个捕获请求
for (int i = 0; i < count; i++) {
CaptureRequest.Builder builder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
builder.addTarget(imageReader.getSurface());
// 配置请求参数...
requests.add(builder.build());
}
// 执行连拍
try {
captureSession.captureBurst(requests, null, null);
} catch (CameraAccessException e) {
// 处理异常
}
}
5. 常见问题排查
5.1 典型问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 相机打开失败 | 权限不足或相机被占用 | 检查权限,确保没有其他应用占用相机 |
| 预览画面卡顿 | 分辨率设置不当 | 选择设备支持的合适分辨率 |
| 对焦不工作 | 模式配置错误 | 检查CONTROL_AF_MODE设置 |
| 拍照延迟高 | 图像处理耗时 | 优化处理流程,考虑使用后台线程 |
5.2 调试技巧
- 启用详细日志:Camera2 API 提供了丰富的状态信息
- 检查CaptureResult:验证实际应用的参数是否符合预期
- 性能分析:使用Android Profiler监控内存和CPU使用情况
- 设备兼容性测试:不同厂商的实现可能有差异
6. 实际应用案例
6.1 专业相机应用开发
开发专业相机应用需要考虑以下高级功能:
- 直方图显示:基于捕获结果的亮度分析
- 焦点峰值:手动对焦辅助功能
- 长曝光控制:实现夜景拍摄模式
- HDR合成:多帧曝光合成
6.2 视频录制优化
高质量视频录制需要注意:
- 帧率稳定:选择合适的帧率和分辨率组合
- 音频同步:正确处理音频和视频的时间戳
- 比特率控制:根据场景动态调整编码参数
- 温度管理:长时间录制时的过热保护
在视频录制实现中,MediaRecorder 与 Camera2 的集成是关键:
java复制public void startRecording(File outputFile) {
// 初始化MediaRecorder
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// 更多配置...
// 准备录制
mediaRecorder.prepare();
// 创建包含预览和录制Surface的会话
List<Surface> surfaces = new ArrayList<>();
surfaces.add(previewSurface);
surfaces.add(mediaRecorder.getSurface());
// 创建会话并开始录制
cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
// 开始录制
mediaRecorder.start();
}
// 其他回调...
}, null);
}
通过 Camera2 API,开发者可以充分发挥现代手机相机的硬件潜力,实现各种专业级摄影功能。掌握这些技术要点后,可以开发出性能优异、功能丰富的相机应用。
