Android USB_DEVICE_ATTACHED 持久权限 [英] Android USB_DEVICE_ATTACHED persistent permission

查看:67
本文介绍了Android USB_DEVICE_ATTACHED 持久权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何让 Android 在每次重新连接 USB 设备时不请求许可?我想让它记住 USB 设备的默认使用"复选标记,这样我就不必每次都向同一设备授予权限.

我以编程方式检测 USB 设备(安卓手机)何时连接到我的主机设备(安卓手机),以便我可以将它们切换到 AOA 模式并将它们用作配件.基本上我有两部安卓手机和一条 OTG 电缆,我希望它们能够相互通信.

I programatically detect when USB devices (android phones) are attached to my host device (android phone) so that I can switch them to AOA mode and use them as accessories. Basically I have two android phones and an OTG cable and I want them to communicate between eachother.

我有一个线程不断枚举连接的 USB 设备:

I have a thread which constantly enumerates the attached USB devices:

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 意图:

I also have a BroadcastReceiver registered to receive USB_PERMISSION intents:

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 模式的方式:

This is how I switch to AOA mode:

  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;
    }

推荐答案

在实现 AOA 时,主要有两种方式来获取 USB 数据传输的设备权限.

In implementing AOA, there are two main ways to obtain device permission for USB data transfers.

一种方法涉及手动枚举所有连接的设备,找到所需的设备,通过 UsbManager.requestPermission(Device device) 方法直接请求许可,并使用 BroadcastReceiver 处理结果广播.这是你写的解决方案.在功能性和合规性的同时,它会在每次连接 USB 设备时提示用户进行许可;用户的潜在烦恼来源.

One approach involves manually enumerating all connected devices, finding the desired device, directly requesting permission via the UsbManager.requestPermission(Device device) method, and handling the resulting broadcast with a BroadcastReceiver. This is the solution you've written. While functional and compliant, it prompts the user for permission every time a USB device is connected; a potential source of annoyance for the user.

另一种方法要简单得多,并且允许使用默认功能.它要求在 AndroidManifest.xml 中定义一个意图过滤器,如下所示:

The other approach is far simpler and allows for use-by-default functionality. It requires that an intent filter be defined in AndroidManifest.xml like so:

<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 文件(只是一个建议,您可以随意命名).这是一个示例附件_过滤器.xml 文件:

Along with an xml file named "accessory_filter"(just a suggestion, you can name it whatever you want). Here's a sample accessory_filter.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" /></resources>

意图过滤器将在设备连接时自动启动应用程序,并为用户提供使用您的应用程序作为您正在使用的特定设备的默认应用程序的选项.

The intent filter will automatically fire up the application in the event of a device connection and presents the user with the option to use your app as the default application for the specific device you are working with.

此链接提供了更多信息:https://developer.android.com/guide/topics/connectivity/usb/accessory#manifest-example

This link provides more information: https://developer.android.com/guide/topics/connectivity/usb/accessory#manifest-example

这篇关于Android USB_DEVICE_ATTACHED 持久权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆