如何在无内置摄像头的安卓媒体播放器上使用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
CameraCharacteristicsto 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.namewith your actual app package name in theACTION_USB_PERMISSIONstring.
内容的提问来源于stack exchange,提问作者Aravind OR

