You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为外接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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:10:27