如何为外接USB相机实现Camera2 API?求有效替代方案
实现平板外接相机的拍照、重拍与保存功能
一、用Camera2 API实现方案
1. 检测外接相机
通过CameraManager枚举所有相机设备,筛选出外接类型的相机:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { String[] cameraIds = manager.getCameraIdList(); for (String id : cameraIds) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(id); // API 30+ 可直接通过CAMERA_TYPE判断外接相机 Integer cameraType = characteristics.get(CameraCharacteristics.CAMERA_TYPE); if (cameraType != null && cameraType == CameraCharacteristics.CAMERA_TYPE_EXTERNAL) { mExternalCameraId = id; break; } // 低版本可结合制造商信息判断(非平板内置品牌的设备大概率为外接) String manufacturer = characteristics.get(CameraCharacteristics.MANUFACTURER); if (manufacturer != null && !manufacturer.equals(Build.MANUFACTURER)) { mExternalCameraId = id; break; } } } catch (CameraAccessException e) { e.printStackTrace(); }
2. 预览与拍照配置
- 使用
TextureView作为预览载体,监听SurfaceTextureListener确保Surface就绪后打开相机。 - 创建
ImageReader接收拍照后的图像数据:
mImageReader = ImageReader.newInstance(1920, 1080, ImageFormat.JPEG, 1); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
- 构建
CameraCaptureSession,绑定预览Surface和ImageReader的Surface:
List<Surface> surfaces = new ArrayList<>(); surfaces.add(new Surface(mTextureView.getSurfaceTexture())); surfaces.add(mImageReader.getSurface()); manager.openCamera(mExternalCameraId, mCameraStateCallback, mBackgroundHandler); // 在CameraDevice.StateCallback的onOpened回调中创建会话 mCameraDevice.createCaptureSession(surfaces, mSessionCallback, mBackgroundHandler);
3. 拍照、重拍与保存
- 拍照:构造静态拍照请求并发送:
CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); captureBuilder.addTarget(mImageReader.getSurface()); // 配置自动对焦与曝光 captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); mCaptureSession.capture(captureBuilder.build(), mCaptureCallback, mBackgroundHandler);
- 重拍:直接重新发送拍照请求即可,注意确保上一次的
Image对象已释放。 - 图片保存:在
ImageReader的回调中处理图像数据并写入文件:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { Image image = reader.acquireLatestImage(); if (image == null) return; ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] imageData = new byte[buffer.remaining()]; buffer.get(imageData); // 写入应用私有外部存储 File photoDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File photoFile = new File(photoDir, "external_cam_photo_" + System.currentTimeMillis() + ".jpg"); try (FileOutputStream fos = new FileOutputStream(photoFile)) { fos.write(imageData); } catch (IOException e) { e.printStackTrace(); } finally { image.close(); } } };
二、替代方案与库
- CameraX:Jetpack封装的相机库,API更简洁,支持外接相机(API 29+)。通过
CameraSelector筛选外接设备,用ImageCapture实现拍照:val cameraSelector = CameraSelector.Builder() .requireCameraType(CameraSelector.LENS_FACING_EXTERNAL) // API 30+ .build() val imageCapture = ImageCapture.Builder().build() // 拍照逻辑 val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build() imageCapture.takePicture(outputOptions, executor, object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { // 保存成功处理 } override fun onError(exception: ImageCaptureException) { // 错误处理 } }) - USB Camera For Android:专注USB外接相机的库,基于USB Host API开发,兼容性优于libuvccamera,支持绝大多数UVC协议的相机,可直接枚举USB相机并获取预览/拍照数据。
- 原生USB Host API:如果以上库都不兼容,可直接通过
UsbManager枚举USB设备,识别符合UVC协议的相机,手动发送USB控制指令获取图像帧,但需要熟悉UVC协议细节,开发成本较高。
内容的提问来源于stack exchange,提问作者Roshni Patel
相关产品推荐
相关产品推荐

