繁体   English   中英

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

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

我有一个 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 代码。

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

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

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

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

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

@alex papa,我购买了三星 Galaxy S10e,尝试使用罗技 c920,但没有获得外部相机 ID。 您能分享一下您使用的网络摄像头吗? 我也 packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 false。

我花了太长时间试图让它发挥作用,所以我想我会与阅读这篇文章的人分享我的发现。 以前的海报已经提到了其中的大部分内容,但希望我可以添加一些有价值的东西。

  1. Android 有Camera2 API ,它似乎支持外部相机。 据说您可以获取每个连接的相机的特征并查找LENS_FACING_EXTERNAL

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

  3. 有一些应用程序,如USB 摄像头,仍然设法使其工作。 我相信他们正在使用像UVCCamera这样的库。 这基本上是一个完整的 UVC(USB 视频类)实现 + USB 主机,最终允许您捕获视频。

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

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

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

这里有一些示例代码,如果您愿意,可以尝试枚举自己手机上的摄像头。 这只是从我自己的实验代码中提取的一些片段,因此错误处理/正确性很差。 但是,它仍然是您需要了解的有关 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 我已尽力确保此信息正确无误。 如果我有什么不对的地方,请不要犹豫纠正我! 关于如何在 Android 上使用外部 USB 摄像头的文档充其量是很少的。

暂无
暂无

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

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