简体   繁体   English

使用 Android-Camera2 API 访问 USB 摄像头

[英]Accessing a USB camera using Android-Camera2 API

I have a UVC camera that want to access and grab frames from in my Android Pie (Android 9) code.我有一个 UVC 摄像头,想要从我的 Android Pie (Android 9) 代码中访问和抓取帧。

This is the code I'm using to enumerate the cameras connected to the Android phone:这是我用来枚举连接到 Android 手机的摄像头的代码:

    @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.我在 Android 9/Pie (Pixel 3) 上跳来跳去,这显示了连接的 USB 摄像头。 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):这是我的清单文件 (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, ie access the USB camera using on Android 9 and later.我在互联网上找不到任何示例代码如何实现这一点,即访问在 Android 9 及更高版本上使用的 USB 摄像头。

What am I missing to get my code enumerate the USB camera?我缺少什么让我的代码枚举 USB 摄像头? I have seen some 3rd party UVC libraries for Android, but I don't to use them and want to use native Android code.我见过一些适用于 Android 的 3rd 方 UVC 库,但我不想使用它们,而是想使用原生 Android 代码。

You can call PackageManager.hasSystemFeature with the constant FEATURE_CAMERA_EXTERNAL to check if your device supports external cameras.您可以使用常量FEATURE_CAMERA_EXTERNAL调用PackageManager.hasSystemFeature来检查您的设备是否支持外部摄像头。 Pixel 3 does not support this feature. Pixel 3 不支持此功能。

Indeed, there are multiple libraries and applications, which offers USB camera support.事实上,有多个库和应用程序提供 USB 摄像头支持。 But they do not use android API and implement everything themselves.但他们不使用 android API 并自己实现一切。 The most common approach seems to use Video for linux kernel module (if the kernel was compiled with this module).最常见的方法似乎是使用Video for linux内核模块(如果内核是用这个模块编译的)。 It also requires permissions to access /dev/video devices, which is not usually the case on non-rooted devices.它还需要访问/dev/video设备的权限,这在非 root 设备上通常不是这种情况。 But the implementation is fairly simple.但实现相当简单。 Eg android-webcam uses this approach.例如android-webcam使用这种方法。

Another approach is to use USB host api and implement all the protocols yourself.另一种方法是使用USB 主机 api并自己实现所有协议。 This does not require root access, but implementation is far more complex.这不需要 root 访问权限,但实现要复杂得多。 You can check this library which goes this way.你可以检查这个库是这样的。

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.我购买了三星 Galaxy S10e ,没有任何修改的完全相同的代码将 USB 摄像头作为列表中的第一个返回。 That is this line Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel);那是这一行Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel); prints 3 times, one for the USB camera and two of the internal cameras.打印 3 次,一次用于 USB 摄像头,两次用于内部摄像头。

My best guess is that most phones designed and manufactured after October 2018 when Android 9 was released do have this feature enabled.我最好的猜测是,大多数在 2018 年 10 月发布 Android 9 之后设计和制造的手机都启用了此功能。 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.大约在那个时间或之前发布然后后来收到 Android 9 (Pie) 更新的手机不太可能具有此功能。

@alex papa, I bought a Samsung Galaxy S10e, tried with logitech c920, but didn't get external camera ID. @alex papa,我购买了三星 Galaxy S10e,尝试使用罗技 c920,但没有获得外部相机 ID。 Can you please share what webcam you use?您能分享一下您使用的网络摄像头吗? I also packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) is returning false.我也 packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 false。

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. Android 有Camera2 API ,它似乎支持外部相机。 You can supposedly get the characteristics for each attached camera and look for one that is LENS_FACING_EXTERNAL .据说您可以获取每个连接的相机的特征并查找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.我在三部三星手机(S9、A31、A51)和一部 Google Pixel 2 XL 上进行了尝试。 This gave me a mix of Android 10 and 11. None of the phones supported external cameras.这给了我 Android 10 和 11 的混合。没有一部手机支持外部摄像头。

  3. There are applications, like USB Camera , that still manages to make it work.有一些应用程序,如USB 摄像头,仍然设法使其工作。 I believe they are making use of libraries like UVCCamera under the hood.我相信他们正在使用像UVCCamera这样的库。 This is basically a complete UVC (USB Video Class) implementation + USB Host , which is what eventually allows you to capture the video.这基本上是一个完整的 UVC(USB 视频类)实现 + USB 主机,最终允许您捕获视频。

  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.我自己决定不使用 UVCCamera 的原因是它没有“Android Blessing”,并且在不同的设备上或在 Android 升级期间,事情可能会以奇怪的方式中断。 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.您可以轻松下载和构建Camera2Video示例( ./gradlew assembleRelease -x test ),因为它为您提供了一个现成的应用程序,可以显示所有检测到的相机。 You would need a USB OTG adapter to plug your webcam into your phone, but you can get those for a few bucks.您需要一个 USB OTG 适配器将网络摄像头插入手机,但只需几美元即可获得。

As things stand right now support for external USB cameras on Android is a bit of a sad story.就目前情况而言,Android 上对外部 USB 摄像头的支持是一个悲伤的故事。 There doesn't seem to be an officially supported way to make use of external USB cameras which works on most devices.似乎没有官方支持的方式来使用适用于大多数设备的外部 USB 摄像头。

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.但是,它仍然是您需要了解的有关 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);        
    }
}

PS I've tried my best to make sure this information is correct. PS 我已尽力确保此信息正确无误。 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.关于如何在 Android 上使用外部 USB 摄像头的文档充其量是很少的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM