序:
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
在进行 Android OTG 开发时(USB摄像头、红外摄像仪、加密U盘等等),需要对 USB 先进行权限读取,获取到可用设备后,才能进行数据的通信。
目前手机主流的 USB 口有两种,micro USB 以及 Type C,可不是我们认为只有数据线大头部分(Type A)才是USB接口,看图就明白了。
下文主要讲关于 Android USB 怎么获取 USB 权限。
USB Host
当Android设备运行过程中,会充当一个 USB host,也就是 USB 主机,USB Host 有个线程循环监测是否有 USB 设备插拔,可链接上 USB 设备并为之供电。
如何读取 USB 权限
1. 静态注册权限
如果你的应用希望接收 USB 通知的话,需要在主 Activty 声明 Intent-filter,并且需要指定过滤的 USB 设备(不指定插上任意 USB 设备,都会打开 APP,别问我咋知道的)。
用当前方式声明,插上指定 USB 设备,就会打开相应 APP 页面,可满足一些功能需求。
<manifest ...>
// 在sdk大于12后,不需要这两行声明
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
...
<application>
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>
device_filter.xml 中包含
- vendor-id (供应商id)
- product-id(产品id)
- class(类)
- subclass(子类)
- protocol(协议接口)
如果只是一般过滤 USB 设备,只需要声明供应商或产品ID(产品id是唯一的),这两个id能具体到某一个设备; 如果您想过滤一组 USB 设备(例如大容量存储设备或数码相机),请使用类、子类和协议。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" protocol="1" />
</resources>
2. 动态申请 USB 权限
在需要的功能页面,动态申请 USB 权限,需要创建个 BroadcastReceiver 监听USB设备的插拔状态(ACTION_USB_DEVICE_ATTACHED 插入、ACTION_USB_DEVICE_DETACHED 拔出)
public synchronized void register() throws IllegalStateException {
if (mPermissionIntent == null) {
if (context != null) {
if (Build.VERSION.SDK_INT >= 31) {
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
} else {
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
}
final IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
// ACTION_USB_DEVICE_ATTACHED never comes on some devices so it should not be added here
filter.addAction(ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
context.registerReceiver(mUsbReceiver, filter);
}
}
}
下文 mUsbManager 是 UsbManager 创建的实例对象,通过 native 方法与 USB 设备通信,需要注意的是,用动态申请的方法,当 UsbManager 的对象销毁后,需要重新对该USB进行授权。
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
// when received the result of requesting USB permission
synchronized (USBMonitor.this) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// 同意获取USB权限
}
} else {
// 拒绝权限
}
}
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null && mUsbManager.hasPermission(device)) {
// 如果插入设备已获得权限,则直接可以使用该 device
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
// Deivce拔出
}
}
};