如何让 Android 在每次重新连接 USB 设备时都不再请求权限?我想让它记住 USB 设备的“默认使用”复选标记,这样我就不必每次都向同一设备授予权限。
我以编程方式检测当USB设备(android手机)连接到我的主机设备(android手机),以便我可以切换到AOA模式,并使用它们作为附件。基本上我有两部Android手机和一条OTG电缆,我希望它们能够相互通信。
我有一个线程,它不断地枚举附加的USB设备:
UsbManager manager = (UsbManager)
context.getSystemService(Context.USB_SERVICE);
while (!m_stopRequested) {
boolean shouldNotify = false;
HashMap<String, UsbDevice> deviceMap = m_usbManager.getDeviceList();
for (Entry<String, UsbDevice> entry : deviceMap) {
UsbDevice device = entry.getValue();
if (m_usbManager.hasPermission(device)) {
int pid = device.getProductId();
if (device.getVendorId() == VID_GOOGLE(0x18D1) && (pid == ACCESSORY_PID(0x2D01) || pid == ACCESSORY_PID_ALT(0x2D00))) {
switchDeviceToAOAMode(device);
}
} else {
m_usbManager.requestPermission(device);
}
}
Thread.sleep(1000);
}
我还注册了一个BroadcastReceiver来接收USB_PERMISSION意图:
private final class USBReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
MCSLogger.log(TAG, "Received permission result!");
String action = intent.getAction();
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (ACTION_USB_PERMISSION.equals(action)) {
boolean res = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
MCSLogger.log(TAG, "permission action for dev=" + device + " received " + res);
int pid = device.getProductId();
if (res && device.getVendorId() == VID_GOOGLE(0x18D1) && (pid == ACCESSORY_PID(0x2D01) || pid == ACCESSORY_PID_ALT(0x2D00))) {
connectAccessory()
}
}
}
};
这是我如何切换到AOA模式的方法:
private boolean switchDeviceToAOAMode(UsbDeviceConnection connection) {
byte ioBuffer[] = new byte[2];
int devVersion;
int response;
enter code here
response = connection.controlTransfer(0xC0, 51, 0, 0, ioBuffer, 2, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error starting transfer control " + response);
return false;
}
devVersion = ioBuffer[1] << 8 | ioBuffer[0];
// sometimes hangs on the next transfer :( //WIN32 libusb only
// SystemClock.sleep(1000);
byte manufacturer[] = m_manufacturer.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 0, manufacturer, manufacturer.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering manufacturer " + response);
return false;
}
byte modelName[] = m_modelName.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 1, modelName, modelName.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering modelName " + response);
return false;
}
byte description[] = m_description.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 2, description, description.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering description " + response);
return false;
}
byte version[] = m_version.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 3, version, version.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering version " + response);
return false;
}
byte uri[] = m_uri.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 4, uri, uri.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering uri " + response);
return false;
}
byte serialNumber[] = m_serialNumber.getBytes();
response = connection.controlTransfer(0x40, 52, 0, 5, serialNumber, serialNumber.length, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error transfering serialNumber " + response);
return false;
}
MCSLogger.log(TAG, "Accessory Identification sent " + devVersion);
response = connection.controlTransfer(0x40, 53, 0, 0, null, 0, 0);
if (response < 0) {
MCSLogger.log(TAG, "Error ending transfer control " + response);
return false;
}
return true;
}
发布于 2019-07-17 15:10:28
在实现AOA时,获取USB数据传输设备权限的方法主要有两种。
一种方法包括手动枚举所有连接的设备,查找所需的设备,通过UsbManager.requestPermission(设备设备)方法直接请求许可,以及使用BroadcastReceiver处理结果广播。这就是你写的解决方案。在功能和遵从性的同时,每次连接USB设备时,它都会提示用户获得许可;这是用户潜在的烦恼源。
另一种方法要简单得多,并允许默认使用功能。它要求在AndroidManifest.xml中定义意图过滤器,如下所示:
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
连同一个名为“accessory_filter”的xml文件(只是一个建议,您可以随意命名它)。下面是一个示例accessory_filter.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" /></resources>
意图筛选器将在设备连接的情况下自动启动应用程序,并向用户提供将应用程序用作正在使用的特定设备的默认应用程序的选项。
此链接提供更多信息:https://developer.android.com/guide/topics/connectivity/usb/accessory#manifest-example
发布于 2019-07-30 23:05:55
@Ender提供的答案是正确的,但在安卓平台(7+)的后期版本中,您还需要做一件事。
您需要确保将android:directBootAware="true"
添加到活动标记中,该标记负责响应USB_ACCESSORY_ATTACHED / USB_DEVICE_ATTACHED权限。
下面是活动的有效清单部分:
<activity android:name=".MainActivity"
android:directBootAware="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb_device_filter" />
</intent-filter>
</activity>
来源:
https://github.com/dazza5000/USBPermissionTest/blob/master/app/src/main/AndroidManifest.xml
usb_device_filter.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="2049" product-id="25"/>
</resources>
来源:
android:directBootAware="true"
提示来自下面的链接,我对此非常感谢。
https://www.sdgsystems.com/post/android-usb-permissions
更多细节可以在这里找到:
https://issuetracker.google.com/issues/77658221
这里有一个完整的工作项目:
https://github.com/dazza5000/USBPermissionTest
根访问
如果您有根访问权限,则可以创建文件并将其写入磁盘,然后重新启动设备,以便读取和设置默认权限。
这些是基本步骤:
私有grantUSBPermission() { UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
for (UsbDevice usbDevice : deviceList.values()) {
if (usbDevice.getManufacturerName() != null && usbDevice.getManufacturerName().equalsIgnoreCase(MANUFACTURER)) {
Boolean hasPermission = usbManager.hasPermission(usbDevice);
// Log if USB manager explicitly reports no permission.
if (!hasPermission) {
Log.i("DARRAN", "USB Manager reporting no permission to reader.");
DeviceFilter deviceFilter = new DeviceFilter(usbDevice);
writeSettingsFile(deviceFilter);
}
}
}
}
private void writeSettingsFile(DeviceFilter deviceFilter) {
PermissionUtil.writeSettingsLocked(getApplicationContext(), deviceFilter);
RootUtil.executeAsRoot(COMMAND_COPY_USB_FILE);
RootUtil.executeAsRoot(COMMAND_CHOWN_USB_FILE);
RootUtil.executeAsRoot("reboot");
}
命令:
public static final String COMMAND_COPY_USB_FILE = "cp /sdcard/Android/data/com.whereisdarran.setusbdefault/files/usb_device_manager.xml /data/system/users/0/usb_device_manager.xml";
public static final String COMMAND_CHOWN_USB_FILE = "chown system:system /data/system/users/0/usb_device_manager.xml";
在这里可以找到一个完整的工作项目:
https://github.com/dazza5000/set-usb-default
另外,一篇有更多背景的博客文章:
https://stackoverflow.com/questions/40075128
复制相似问题