【问题标题】:Accessing a USB camera using Android-Camera2 API使用 Android-Camera2 API 访问 USB 摄像头
【发布时间】:2020-01-10 18:39:43
【问题描述】:

我有一个 UVC 相机,它想从我的 Android Pie (Android 9) 代码中访问和抓取帧。

这是我用来枚举连接到 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();
        }
    }

我在使用 Android 9/Pie (Pixel 3) 时显示已连接的 USB 摄像头。但是只列出了两个设备,手机的前置和后置摄像头。

这是我的清单文件 (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" />

我在互联网上找不到任何示例代码如何实现这一点,即在 Android 9 及更高版本上使用 USB 摄像头。

为了让我的代码枚举 USB 摄像头,我缺少什么?我见过一些适用于 Android 的 3rd 方 UVC 库,但我不使用它们,而是想使用原生 Android 代码。

【问题讨论】:

  • @Daniel 我的理解是,在该页面上可以找到 Android 设备制造商所需的信息,例如三星。对于像这样的最终开发人员来说,页面上没有什么有用的。还是我错过了什么?

标签: java android android-camera2


【解决方案1】:

您可以使用常量FEATURE_CAMERA_EXTERNAL 调用PackageManager.hasSystemFeature,以检查您的设备是否支持外接摄像头。 Pixel 3 不支持此功能。

确实,有多个库和应用程序提供 USB 摄像头支持。但他们不使用 android API 并自己实现所有内容。最常见的方法似乎是使用Video for linux 内核模块(如果内核是用这个模块编译的)。它还需要访问/dev/video 设备的权限,这在非root 设备上通常不是这种情况。但实现相当简单。例如。 android-webcam 使用这种方法。

另一种方法是使用USB host api 并自己实现所有协议。这不需要 root 访问权限,但实现要复杂得多。你可以检查this library是这样的。

【讨论】:

  • 你知道肯定支持外接摄像头的安卓设备吗?
  • @fireant 不,我检查了一些三星、华为、Pixel、HTC,但没有一个支持它。我相信这个功能更适用于 Android TV 和其他类型的设备,而不是手机。
  • @esentsov 您是否查看了这些制造商的最新设备? OP 表示三星 S10e 支持开箱即用的外接摄像头。我也在寻找原生支持 UVC 摄像头的设备。
  • 不,我无权访问 S10e。我相信上次我用 S9+ 和像素 3 检查过它,但它没有工作。目前我没有任何原生支持它的设备:(
  • Note9 支持外接 USB 摄像头,但仅限于专门寻找它并被授予外接摄像头权限的应用程序中。 Chrome 等应用无法检测到它。
【解决方案2】:

我想我找到了自己问题的答案。我购买了 Samsung Galaxy S10e 并且相同的代码没有任何修改返回 USB 摄像头作为列表中的第一个。也就是Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel); 这一行打印了 3 次,一个用于 USB 摄像头,两个用于内部摄像头。

我的最佳猜测是,大多数在 2018 年 10 月 Android 9 发布之后设计和制造的手机都启用了此功能。大约在那个时候或之前发布的手机,后来又收到了 Android 9 (Pie) 的更新,不太可能有这个功能。

【讨论】:

  • @alex-papa 您怎么知道要购买哪种设备? Chrome 能否检测到您的摄像头(例如使用 webcamtests.com)?
  • 感谢您提供此信息。如果默认不支持(即不支持本机支持),有没有办法通过用户空间程序带来这种支持(UVC 功能)而不触发系统构建。我需要通过我的设备连接到两个 USB 摄像头,并使用我的应用程序中的 Camera2 APi 获取帧。
  • 是否可以通过 Camera2 API 或 cameraX 访问外部 USB 摄像头?
  • 等 Samsung Galaxy S10e packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 true 而在 Samsung Galaxy S10 上返回 false?
【解决方案3】:

我花了太长时间试图让它发挥作用,所以我想我会与任何阅读本文的人分享我的发现。之前的海报中已经提到了很多,但希望我能增加一些有价值的东西。

  1. Android 有Camera2 API,它似乎支持外部摄像头。您应该可以获取每个连接的摄像头的特征并查找LENS_FACING_EXTERNAL。

  2. 实际上这似乎不适用于许多手机。我在三部三星手机(S9、A31、A51)和一部 Google Pixel 2 XL 上进行了试用。这让我混合使用了 Android 10 和 11。这些手机都不支持外接摄像头。

  3. 有一些应用程序,比如USB Camera,仍然可以让它工作。我相信他们正在使用像 UVCCamera 这样的库。这基本上是一个完整的 UVC(USB 视频类)实现 + USB Host,最终允许您捕获视频。

  4. 我自己决定不使用 UVCCamera 的原因是它没有“Android Blessing”,而且在不同的设备上或在 Android 升级期间,事情可能会以奇怪的方式发生故障。我自己没有能力支持。

  5. 您可以轻松下载并构建 Camera2Video 示例 (./gradlew assembleRelease -x test),因为它为您提供了一个现成的应用程序,可以显示所有检测到的摄像头。您需要一个 USB OTG 适配器才能将您的网络摄像头插入您的手机,但您只需花几美元就可以买到。

就目前的情况而言,Android 上支持外部 USB 摄像头有点令人悲伤。似乎没有官方支持的方式来使用适用于大多数设备的外部 USB 摄像头。

这里有一些示例代码,您可以根据需要尝试枚举自己手机上的摄像头。这只是从我自己的实验代码中提取的几个 sn-ps,因此错误处理/正确性很差。但是,它仍然是您需要了解的有关 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);        
    }
}

附: 我已尽力确保此信息正确无误。如果我有什么问题,请不要犹豫,纠正我!关于如何在 Android 上使用外部 USB 摄像头的文档充其量是很少的。

【讨论】:

    【解决方案4】:

    @alex 爸爸, 我买了三星 Galaxy S10e,用罗技 c920 试过,但没有得到外接摄像头 ID。你能分享一下你使用的网络摄像头吗?我也 packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 false。

    【讨论】:

    • 当您在 Chrome 中打开视频时,您能否在 webcamtests.com 上看到来自外部网络摄像头的视频?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多