使用 Android-Camera2 API 访问 USB 摄像头
Accessing a USB camera using Android-Camera2 API
我有一个 UVC 相机,想从我的 Android Pie (Android 9) 代码中访问和抓取帧。
这是我用来枚举连接到 Android phone 的摄像头的代码:
@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 摄像头。但是只列出了两个设备,前置和后置摄像头 og phone。
这是我的清单文件 (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 的第 3 方 UVC 库,但我不想使用它们,而是想使用本机 Android 代码。
您可以致电PackageManager.hasSystemFeature with the constant FEATURE_CAMERA_EXTERNAL检查您的设备是否支持外置摄像头。 Pixel 3 不支持此功能。
的确,有多个库和应用程序提供 USB 摄像头支持。但他们不使用 android API 并自己实现所有内容。最常见的方法似乎是使用 Video for linux kernel module (if the kernel was compiled with this module). It also requires permissions to access /dev/video
devices, which is not usually the case on non-rooted devices. But the implementation is fairly simple. E.g. android-webcam 使用这种方法。
另一种方法是使用 USB host api and implement all the protocols yourself. This does not require root access, but implementation is far more complex. You can check this library 这样的方法。
我想我找到了我自己问题的答案。我购买了 Samsung Galaxy S10e 和完全相同的代码,没有任何修改 returns USB 相机作为列表中的第一个。即此行 Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel);
打印 3 次,一次用于 USB 摄像头,两次用于内部摄像头。
我最好的猜测是,大多数在 2018 年 10 月 Android 9 发布后设计和制造的 phone 都启用了此功能。大约那个时候或之前发布的 phone 然后后来收到 Android 9 (Pie) 的更新不太可能有此功能。
@alex 爸爸,
我买了三星 Galaxy S10e,尝试使用罗技 c920,但没有获得外部摄像头 ID。你能分享一下你使用的网络摄像头吗?我也 packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 false。
我花了太长时间试图让它发挥作用,所以我想我会与阅读本文的人分享我的发现。之前的发帖者已经提到了其中的大部分内容,但希望我可以添加一些有价值的东西。
Android 有 Camera2 API 似乎支持外置摄像头。据推测,您可以获得每个连接的相机的特征并寻找一个 LENS_FACING_EXTERNAL
.
实际上这似乎还不适用于很多 phone。我在三台三星 phones(S9、A31、A51)和一台 Google Pixel 2 XL 上进行了测试。这给了我 Android 10 和 11 的组合。 phone 中的 None 支持外部摄像头。
有一些应用程序,例如 USB Camera, that still manages to make it work. I believe they are making use of libraries like UVCCamera under the hood. This is basically a complete UVC (USB Video Class) implementation + USB Host,最终允许您捕获视频。
我自己决定不使用 UVCCamera 的原因是它没有“Android 祝福”,并且在不同的设备上或在 Android升级。我自己没有能力支持那个。
您可以轻松下载并构建 Camera2Video 示例 (./gradlew assembleRelease -x test
),因为它为您提供了一个现成的应用程序,可以显示所有检测到的摄像头。您需要一个 USB OTG 适配器才能将您的网络摄像头插入您的 phone,但您可以花几美元购买。
就目前的情况而言,Android 对外部 USB 摄像头的支持有点令人难过。似乎没有官方支持的方式来使用适用于大多数设备的外部 USB 摄像头。
这里有一些示例代码,您可以根据需要尝试自己枚举相机 phone。这只是从我自己的实验代码中提取的几个片段,所以错误处理/正确性很差。但是,它仍然是您需要了解的有关 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);
}
}
P.S。
我已尽力确保此信息正确无误。如果我有什么不对的地方,请不要犹豫纠正我!关于如何在 Android 上使用外部 USB 摄像头的文档充其量是稀疏的。
我有一个 UVC 相机,想从我的 Android Pie (Android 9) 代码中访问和抓取帧。
这是我用来枚举连接到 Android phone 的摄像头的代码:
@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 摄像头。但是只列出了两个设备,前置和后置摄像头 og phone。
这是我的清单文件 (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 的第 3 方 UVC 库,但我不想使用它们,而是想使用本机 Android 代码。
您可以致电PackageManager.hasSystemFeature with the constant FEATURE_CAMERA_EXTERNAL检查您的设备是否支持外置摄像头。 Pixel 3 不支持此功能。
的确,有多个库和应用程序提供 USB 摄像头支持。但他们不使用 android API 并自己实现所有内容。最常见的方法似乎是使用 Video for linux kernel module (if the kernel was compiled with this module). It also requires permissions to access /dev/video
devices, which is not usually the case on non-rooted devices. But the implementation is fairly simple. E.g. android-webcam 使用这种方法。
另一种方法是使用 USB host api and implement all the protocols yourself. This does not require root access, but implementation is far more complex. You can check this library 这样的方法。
我想我找到了我自己问题的答案。我购买了 Samsung Galaxy S10e 和完全相同的代码,没有任何修改 returns USB 相机作为列表中的第一个。即此行 Log.d(TAG, " **** device ["+cameraId+"] level:"+deviceLevel);
打印 3 次,一次用于 USB 摄像头,两次用于内部摄像头。
我最好的猜测是,大多数在 2018 年 10 月 Android 9 发布后设计和制造的 phone 都启用了此功能。大约那个时候或之前发布的 phone 然后后来收到 Android 9 (Pie) 的更新不太可能有此功能。
@alex 爸爸, 我买了三星 Galaxy S10e,尝试使用罗技 c920,但没有获得外部摄像头 ID。你能分享一下你使用的网络摄像头吗?我也 packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) 返回 false。
我花了太长时间试图让它发挥作用,所以我想我会与阅读本文的人分享我的发现。之前的发帖者已经提到了其中的大部分内容,但希望我可以添加一些有价值的东西。
Android 有 Camera2 API 似乎支持外置摄像头。据推测,您可以获得每个连接的相机的特征并寻找一个
LENS_FACING_EXTERNAL
.实际上这似乎还不适用于很多 phone。我在三台三星 phones(S9、A31、A51)和一台 Google Pixel 2 XL 上进行了测试。这给了我 Android 10 和 11 的组合。 phone 中的 None 支持外部摄像头。
有一些应用程序,例如 USB Camera, that still manages to make it work. I believe they are making use of libraries like UVCCamera under the hood. This is basically a complete UVC (USB Video Class) implementation + USB Host,最终允许您捕获视频。
我自己决定不使用 UVCCamera 的原因是它没有“Android 祝福”,并且在不同的设备上或在 Android升级。我自己没有能力支持那个。
您可以轻松下载并构建 Camera2Video 示例 (
./gradlew assembleRelease -x test
),因为它为您提供了一个现成的应用程序,可以显示所有检测到的摄像头。您需要一个 USB OTG 适配器才能将您的网络摄像头插入您的 phone,但您可以花几美元购买。
就目前的情况而言,Android 对外部 USB 摄像头的支持有点令人难过。似乎没有官方支持的方式来使用适用于大多数设备的外部 USB 摄像头。
这里有一些示例代码,您可以根据需要尝试自己枚举相机 phone。这只是从我自己的实验代码中提取的几个片段,所以错误处理/正确性很差。但是,它仍然是您需要了解的有关 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);
}
}
P.S。 我已尽力确保此信息正确无误。如果我有什么不对的地方,请不要犹豫纠正我!关于如何在 Android 上使用外部 USB 摄像头的文档充其量是稀疏的。