告别Camera1!Android Camera2 API实战:从零搭建一个带拍照功能的简易相机App
Android Camera2 API实战从零构建高性能相机应用在移动应用开发领域相机功能始终是用户体验的核心环节之一。随着Android 5.0(Lollipop)的发布Google彻底重构了相机框架推出了Camera2 API以替代已显老态的Camera1接口。这一变革不仅带来了更精细的硬件控制能力也为开发者开辟了更广阔的创意空间。1. Camera2 API架构解析Camera2 API采用全新的管道(Pipeline)设计模式将相机操作抽象为请求(Request)和会话(Session)的概念体系。这种设计显著提升了框架的灵活性和可控性使开发者能够实现诸如手动曝光控制、高速连拍等Camera1难以企及的功能。核心组件包括CameraManager系统级服务负责枚举和访问相机设备CameraDevice代表物理相机设备的抽象CameraCaptureSession管理相机数据流的传输管道CaptureRequest定义单次图像捕获的参数配置CaptureResult提供捕获操作的元数据反馈与传统Camera1 API的简单回调机制不同Camera2引入了状态机模型。典型工作流程如下// 伪代码展示Camera2基本工作流 CameraManager manager (CameraManager) context.getSystemService(CAMERA_SERVICE); String cameraId manager.getCameraIdList()[0]; manager.openCamera(cameraId, new CameraDevice.StateCallback() { Override public void onOpened(NonNull CameraDevice camera) { // 设备就绪后创建会话 camera.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { Override public void onConfigured(NonNull CameraCaptureSession session) { // 会话就绪后构建并提交请求 CaptureRequest.Builder builder camera.createCaptureRequest(TEMPLATE_PREVIEW); builder.addTarget(previewSurface); session.setRepeatingRequest(builder.build(), null, null); } }, null); } }, null);2. 开发环境准备2.1 基础配置要求确保开发环境满足以下条件Android Studio 4.0Gradle插件版本7.0编译SDK版本≥21Android 5.0目标设备系统版本≥5.0在build.gradle中添加必要依赖dependencies { implementation androidx.appcompat:appcompat:1.4.1 implementation androidx.camera:camera-core:1.1.0 implementation androidx.camera:camera-camera2:1.1.0 }2.2 权限声明在AndroidManifest.xml中添加相机和存储权限uses-permission android:nameandroid.permission.CAMERA / uses-feature android:nameandroid.hardware.camera / uses-feature android:nameandroid.hardware.camera.autofocus / uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE android:maxSdkVersion28 /注意从Android 10开始作用域存储限制要求使用MediaStore API替代直接文件访问3. 相机功能实现详解3.1 相机初始化流程完整的相机初始化包含以下关键步骤获取CameraManager实例CameraManager manager (CameraManager) getSystemService(Context.CAMERA_SERVICE);检查相机特性CameraCharacteristics characteristics manager.getCameraCharacteristics(cameraId); StreamConfigurationMap map characteristics.get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size[] previewSizes map.getOutputSizes(SurfaceTexture.class);打开相机设备manager.openCamera(cameraId, new CameraDevice.StateCallback() { Override public void onOpened(NonNull CameraDevice camera) { // 设备准备就绪 } Override public void onDisconnected(NonNull CameraDevice camera) { camera.close(); } }, null);3.2 预览功能实现预览功能需要配置SurfaceView或TextureView作为渲染目标// 创建预览Surface SurfaceTexture texture textureView.getSurfaceTexture(); texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); Surface previewSurface new Surface(texture); // 创建会话 cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface()), new CameraCaptureSession.StateCallback() { Override public void onConfigured(NonNull CameraCaptureSession session) { // 构建预览请求 CaptureRequest.Builder builder cameraDevice.createCaptureRequest( CameraDevice.TEMPLATE_PREVIEW); builder.addTarget(previewSurface); session.setRepeatingRequest(builder.build(), null, null); } }, null);3.3 拍照功能实现拍照流程需要配置ImageReader接收图像数据// 初始化ImageReader ImageReader imageReader ImageReader.newInstance( captureSize.getWidth(), captureSize.getHeight(), ImageFormat.JPEG, 2); imageReader.setOnImageAvailableListener(reader - { Image image reader.acquireNextImage(); // 处理图像数据 image.close(); }, handler); // 构建拍照请求 CaptureRequest.Builder builder cameraDevice.createCaptureRequest( CameraDevice.TEMPLATE_STILL_CAPTURE); builder.addTarget(imageReader.getSurface()); session.capture(builder.build(), null, null);4. 高级功能开发技巧4.1 手动控制参数Camera2允许精细控制各种相机参数// 手动设置曝光时间纳秒 builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 10000000L); // 设置ISO感光度 builder.set(CaptureRequest.SENSOR_SENSITIVITY, 800); // 手动对焦 builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF); builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.5f);4.2 连拍功能实现通过批量提交请求实现高速连拍ListCaptureRequest requests new ArrayList(); for (int i 0; i 10; i) { CaptureRequest.Builder builder cameraDevice.createCaptureRequest( CameraDevice.TEMPLATE_STILL_CAPTURE); builder.addTarget(imageReader.getSurface()); requests.add(builder.build()); } session.captureBurst(requests, null, null);4.3 图像后处理管道结合RenderScript实现实时滤镜效果// 创建输入/输出Allocation Allocation input Allocation.createFromBitmap(rs, inputBitmap); Allocation output Allocation.createTyped(rs, input.getType()); // 创建并执行脚本 ScriptC_grayscale grayscale new ScriptC_grayscale(rs); grayscale.forEach_root(input, output); output.copyTo(outputBitmap);5. 性能优化实践5.1 内存管理策略优化项实现方法效果评估Surface复用使用SurfaceView替代TextureView减少30%内存拷贝图像缓冲区合理设置ImageReader的maxImages平衡延迟与内存占用请求批处理使用captureBurst替代多次capture提升15%连拍速度5.2 异步操作模式关键操作应使用Handler切换到非UI线程HandlerThread thread new HandlerThread(CameraBackground); thread.start(); Handler handler new Handler(thread.getLooper()); manager.openCamera(cameraId, new CameraDevice.StateCallback() { // ... }, handler);5.3 错误处理机制完善的错误处理应包含以下场景相机权限被拒绝设备被其他应用占用不支持的参数组合低光照条件下的对焦失败Override public void onError(NonNull CameraDevice camera, int error) { switch (error) { case ERROR_CAMERA_DEVICE: // 致命错误需要重新初始化 break; case ERROR_CAMERA_DISABLED: // 设备策略限制 break; case ERROR_CAMERA_IN_USE: // 相机被占用 break; } camera.close(); }在Camera2 API的实际应用中调试复杂的异步回调链往往最具挑战性。建议使用系统提供的Camera2Basic示例作为起点逐步添加功能模块。当遇到图像方向问题时检查CameraCharacteristics.SENSOR_ORIENTATION当预览卡顿时确认是否错误地使用了阻塞式图像处理方式。