18

I have a UVC camera that want to access and grab frames from in my Android Pie (Android 9) code.

This is the code I'm using to enumerate the cameras connected to the Android phone:

    @Override
    public void onResume()
    {
        CameraManager manager =
                (CameraManager)getSystemService(CAMERA_SERVICE);
        try {
            for (String cameraId : manager.getCameraIdList()) {
                CameraCharacteristics chars
                        = manager.getCameraCharacteristics(cameraId);
                // Do something with the characteristics
                int deviceLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel);
            }
        } catch(CameraAccessException e){
            e.printStackTrace();
        }
    }

I was hopping on Android 9/Pie (Pixel 3) this shows the connected USB camera. But only two devices get listed, the front and back cameras og the phone.

This is the list of features and permissions in my manifest file (AndroidManifest.xml):

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.usb.host" />

I cannot find any sample code on the internet how to achieve this, i.e. access the USB camera using on Android 9 and later.

What am I missing to get my code enumerate the USB camera? I have seen some 3rd party UVC libraries for Android, but I don't to use them and want to use native Android code.

alex papa
  • 616
  • 1
  • 4
  • 10
  • 1
    have you tried this? https://source.android.com/devices/camera/external-usb-cameras – Daniel Sep 09 '19 at 00:15
  • 12
    @Daniel My understanding is that on that page one can find the info needed for Android device manufacturers, say Samsung. There is nothing useful on the page for an end developer like. Or I'm missing something? – alex papa Sep 09 '19 at 00:25

3 Answers3

14

I spent way too long trying to get this to work, so I thought I'd share my findings with whoever reads this. Much of it has already been mentioned by previous posters, but hopefully I can add something of value.

  1. Android has the Camera2 API which seems to support external cameras. You can supposedly get the characteristics for each attached camera and look for one that is LENS_FACING_EXTERNAL.

  2. Practically speaking this doesn't seem to work on many phones yet. I tried it on three Samsung phones (S9, A31, A51) and one Google Pixel 2 XL. This gave me a mix of Android 10 and 11. None of the phones supported external cameras.

  3. There are applications, like USB Camera, that still manages to make it work. I believe they are making use of libraries like UVCCamera under the hood. This is basically a complete UVC (USB Video Class) implementation + USB Host, which is what eventually allows you to capture the video.

  4. The reason I decided against using UVCCamera myself is that it doesn't have the "Android Blessing", and things might break in weird ways on different devices, or during Android upgrades. I myself don't have the capacity to support that.

  5. You can easily download and build the Camera2Video sample (./gradlew assembleRelease -x test) since that gives you a ready made app which shows you all the detected cameras. You would need a USB OTG adapter to plug your webcam into your phone, but you can get those for a few bucks.

As things stand right now support for external USB cameras on Android is a bit of a sad story. There doesn't seem to be an officially supported way to make use of external USB cameras which works on most devices.

Here's a bit of sample code that allows you to try to enumerate the cameras on your own phone if you feel like it. It's just a few snippets lifted from my own experimental code, so error handling / correctness is bad. However, it's still the most important bits and pieces of code you need to know about AFAIK.

public class CameraUtils {
    final Context context;
    final CameraManager cameraManager;
    
    public CameraUtils(Context context) {      
        this.context = context;  
        this.cameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
    }
    
    /** 
    * Get the IDs of all available cameras.
    */
    public String[] getCameraIds() {
        return this.cameraManager.getCameraIdList();
    }
        
    /**
    * Get the "lens facing" for a particular camera ID returned by `getCameraIds()`.
    */
    public bool getLensFacing(String cameraId) {        
        CameraCharacteristics characteristics = this.cameraManager.getCameraCharacteristics(cameraId);
        
        // This will return one of CameraMetadata.LENS_FACING_FRONT,
        // CameraMetadata.LENS_FACING_BACK or CameraMetadata.LENS_FACING_EXTERNAL.
        return characteristics.get(CameraCharacteristics.LENS_FACING);
    }
    
    /**
    * Return true if this kernel supports external cameras, false otherwise.
    */
    public bool supportsExternalCameras() {
        return this.context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL);        
    }
}

P.S. I've tried my best to make sure this information is correct. If I got something wrong, please don't hesitate to correct me! The documentation on how to use external USB cameras on Android is sparse at best.

Erik Näslund
  • 1,196
  • 11
  • 9
  • hi @Erik, it is not supported in a wide variety of devices not supported in my MI device, so what is the solution you are working with now? – lazydevpro Jun 20 '22 at 13:34
  • 1
    @lazydevpro I actually gave up on the project I'm afraid, because I never found a way that was supported on the majority of devices. – Erik Näslund Jun 20 '22 at 13:47
  • oh, np mate thanks for taking the time I think I have to try UVCCamera now, even that library is a nightmare to refactor so old:( – lazydevpro Jun 20 '22 at 17:18
10

You can call PackageManager.hasSystemFeature with the constant FEATURE_CAMERA_EXTERNAL to check if your device supports external cameras. Pixel 3 does not support this feature.

Indeed, there are multiple libraries and applications, which offers USB camera support. But they do not use android API and implement everything themselves. The most common approach seems to use Video for linux kernel module (if the kernel was compiled with this module). It also requires permissions to access /dev/video devices, which is not usually the case on non-rooted devices. But the implementation is fairly simple. E.g. android-webcam uses this approach.

Another approach is to use USB host api and implement all the protocols yourself. This does not require root access, but implementation is far more complex. You can check this library which goes this way.

esentsov
  • 6,372
  • 21
  • 28
  • Do you know an Android device that for sure supports external cameras? – fireant Sep 11 '19 at 20:29
  • 1
    @fireant No, I checked a few Samsungs, Huaweis, Pixels, HTCs and none of them supports it. I believe this feature is more for Android TV and other types of devices, not for phones. – esentsov Sep 12 '19 at 11:08
  • @esentsov did you check the latest devices from those manufacturers? The OP says Samsung S10e supported external cameras out of the box. I too am looking for devices that support UVC cams natively. – Froschgesicht Dec 06 '19 at 16:16
  • 1
    No, I don't have access to S10e. I believe last time I checked it with S9+ and pixel 3 and it did not work. Currently I don't have any devices that support it natively :( – esentsov Dec 12 '19 at 06:52
  • Note9 supports external USB camera, but only in apps that specifically look for it and are granted external camera permission. Apps like a Chrome don't detect it. – Radzor Apr 25 '21 at 22:36
  • Hello! I have this problem too, seems like Android's camera API didn't support all devices. Any solution or feedback using the external library (UVCCamera), which I think it is not compatible to the latest version and no more maintained anymore.. thank you! – Evan Gunawan May 28 '21 at 08:44
10

I think I found the answer to my own question. I purchased a Samsung Galaxy S10e and the same exact code without any modification returns the USB camera as the first one in the list. That is this line Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel); prints 3 times, one for the USB camera and two of the internal cameras.

My best guess is that most phones designed and manufactured after October 2018 when Android 9 was released do have this feature enabled. The phone that were released about that time or before and then later received an update to Android 9 (Pie) are unlikely to have this feature.

alex papa
  • 616
  • 1
  • 4
  • 10
  • 1
    @alex-papa How did you know which device to purchase? Can Chrome detect your camera (for example using webcamtests.com)? – Froschgesicht Dec 06 '19 at 16:12
  • Thanks for this info. If it is not supported by default(i.e. no native support), is there any way to bring this support (UVC feature) through user-space programs without triggering the system build. I need to connect to two USB camera's through my device and fetch the frames using Camera2 APi from my application. – Vidz Jun 28 '20 at 14:01
  • 1
    is it possible to access external USB Camera with Camera2 API or cameraX? – Chetan Chaudhari Jul 29 '20 at 12:16
  • 3
    so on **Samsung Galaxy S10e** `packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL)` returns `true` while on **Samsung Galaxy S10** it returns `false`? – user924 Jan 21 '21 at 16:36