簡體   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