[英]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。
我花了太長時間試圖讓它發揮作用,所以我想我會與閱讀這篇文章的人分享我的發現。 以前的海報已經提到了其中的大部分內容,但希望我可以添加一些有價值的東西。
Android 有Camera2 API ,它似乎支持外部相機。 據說您可以獲取每個連接的相機的特征並查找LENS_FACING_EXTERNAL
。
實際上,這似乎不適用於許多手機。 我在三部三星手機(S9、A31、A51)和一部 Google Pixel 2 XL 上進行了嘗試。 這給了我 Android 10 和 11 的混合。沒有一部手機支持外部攝像頭。
有一些應用程序,如USB 攝像頭,仍然設法使其工作。 我相信他們正在使用像UVCCamera這樣的庫。 這基本上是一個完整的 UVC(USB 視頻類)實現 + USB 主機,最終允許您捕獲視頻。
我自己決定不使用 UVCCamera 的原因是它沒有“Android Blessing”,並且在不同的設備上或在 Android 升級期間,事情可能會以奇怪的方式中斷。 我自己沒有能力支持這一點。
您可以輕松下載和構建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.