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

如何在无内置摄像头的安卓媒体播放器上使用Android CameraX访问外接USB摄像头?

Got it, let's work through this. The problem here is that CameraX's default back/front camera selectors only look for built-in cameras—they don't recognize external USB cams out of the box. Since Open Camera works, your device and camera are compatible with Android's USB video support, so we just need to adjust your CameraX code to target the external camera.

Step 1: Add Required Permissions to Your Manifest

First, make sure your app has the permissions needed to access cameras and USB devices:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" />

Step 2: Handle USB Permission Requests

Android requires explicit user permission to access external USB devices. Add a broadcast receiver to listen for permission results and request access to the camera device:

private static final String ACTION_USB_PERMISSION = "com.your.package.name.USB_PERMISSION";
private UsbManager usbManager;
private BroadcastReceiver usbPermissionReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // Initialize USB manager and permission receiver
    usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    usbPermissionReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            // Permission granted, start the camera
                            startCamera();
                        }
                    } else {
                        Toast.makeText(context, "USB camera permission denied", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    };
    
    // Register the receiver
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    registerReceiver(usbPermissionReceiver, filter);
    
    // Check for connected USB cameras and request permission
    HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
    if (!deviceList.isEmpty()) {
        // Look for video class devices (standard UVC cameras)
        for (UsbDevice device : deviceList.values()) {
            if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) {
                PendingIntent permissionIntent = PendingIntent.getBroadcast(
                        this, 0, new Intent(ACTION_USB_PERMISSION), 
                        PendingIntent.FLAG_IMMUTABLE // Use FLAG_MUTABLE if targeting < API 31
                );
                usbManager.requestPermission(device, permissionIntent);
                break;
            }
        }
    } else {
        Toast.makeText(this, "No USB devices detected", Toast.LENGTH_SHORT).show();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // Clean up the receiver to avoid memory leaks
    unregisterReceiver(usbPermissionReceiver);
}

Step 3: Modify startCamera() to Target the USB Camera

Instead of using the default back/front selectors, we'll iterate through all available cameras and pick the external USB one:

private void startCamera() {
    ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
    Preview preview = new Preview.Builder().build();
    preview.setSurfaceProvider(viewFinder.getSurfaceProvider());
    imageCapture = new ImageCapture.Builder().build();

    cameraProviderFuture.addListener(() -> {
        try {
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
            cameraProvider.unbindAll();

            // Find the external USB camera
            CameraSelector usbCameraSelector = null;
            for (CameraInfo cameraInfo : cameraProvider.getAvailableCameraInfos()) {
                boolean isExternalCamera;

                // Direct check for API 30+ (CameraX added this method)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    isExternalCamera = cameraInfo.getCameraType() == CameraInfo.CAMERA_TYPE_EXTERNAL;
                } else {
                    // Fallback for older APIs using Camera2 characteristics
                    CameraCharacteristics characteristics = cameraInfo.getCameraCharacteristics();
                    Integer deviceType = characteristics.get(CameraCharacteristics.DEVICE_TYPE);
                    isExternalCamera = deviceType != null && deviceType == CameraCharacteristics.DEVICE_TYPE_EXTERNAL;
                }

                if (isExternalCamera) {
                    // Create a selector targeting this specific external camera
                    usbCameraSelector = new CameraSelector.Builder()
                            .addCameraFilter(infos -> {
                                for (CameraInfo info : infos) {
                                    if (info.equals(cameraInfo)) {
                                        return Collections.singletonList(info);
                                    }
                                }
                                return Collections.emptyList();
                            })
                            .build();
                    break;
                }
            }

            if (usbCameraSelector != null) {
                // Bind the lifecycle to the external camera
                cameraProvider.bindToLifecycle(this, usbCameraSelector, preview, imageCapture);
            } else {
                Toast.makeText(this, "No external USB camera found", Toast.LENGTH_SHORT).show();
            }

        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
            Toast.makeText(this, "Camera initialization failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }, ContextCompat.getMainExecutor(this));
}

Key Notes

  • Most USB cameras use the UVC (USB Video Class) standard, which Android supports natively. Since Open Camera works, your camera is almost certainly UVC-compliant.
  • For API levels below 30, we rely on Camera2's CameraCharacteristics to identify external devices—this is a reliable fallback since CameraX's direct external camera check was added in API 30.
  • Don't forget to replace com.your.package.name with your actual app package name in the ACTION_USB_PERMISSION string.

内容的提问来源于stack exchange,提问作者Aravind OR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:32:33