使用“设备过滤器”解决方案时如何处理 Android 上的 USB 权限对话框事件?

2024-02-19

当我将“已知”USB 设备连接到 Android 手机时出现的自动权限对话框中,用户按下“确定”或“取消”时,我试图处理该事件。

我正在使用 android.usb.host 库,可以在 Android 手机和设备之间发送和接收。此外,我使用 BroadcastReceiver 处理“USB_DEVICE_ATTACHED”和“USB_DEVICE_DETACHED”没有任何问题。

我想启用一种“自动连接”功能,因此我需要知道用户何时在自动显示的权限对话框中按下“确定”,但我根本无法在网上找到任何内容。我找到的只是“绕过对话框”,但这不是我想要或需要的。

当我将 USB 设备连接到 Android 手机时,会自动显示一个权限对话框,因为我使用了 Android 文档中的“device_filter.xml”解决方案,可以在此处查看Android USB 文档 https://developer.android.com/guide/topics/connectivity/usb/host#permission-d.

这是我处理 USB_DEVICE_ATTACHED 和 USB_DEVICE_DETACHED 事件的方式:


  public NativeUsbService(ReactApplicationContext reactContext) {
    ...
    // register device attached/detached event listeners
    IntentFilter filter = new IntentFilter();
    filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

    reactContext.registerReceiver(usbReceiver, filter);
    ...
  }

然后是广播接收器:

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
        synchronized (this) {
          UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

          if(device != null){
            usbDevice = device;
          } else {
            Log.d(TAG, "onReceive: DEVICE WAS ATTACHED AND WAS NULL :(");
          }
        }
      } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
        Log.d(TAG, "onReceive: Device was detached!");
        if(connection != null) {
          connection.releaseInterface(usbDeviceInterface);
          connection.close();
        }
        connection = null;
        usbDevice = null;
        endpointIn = null;
        endpointOut = null;
      }
    }
  };

我尝试了多种不同的方法,但没有任何效果。

我尝试从意图中获取用户响应,例如使用手动权限请求,如下所示:

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
        synchronized (this) {
          UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

          if(device != null){
            usbDevice = device;

            // THIS DOES NOT WORK ↓↓↓
            if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
              // The code never gets here...
            }

          } else {
              Log.d(TAG, "onReceive: DEVICE WAS ATTACHED AND WAS NULL :(");
              sendEvent("onDeviceAttached", false);
          }

        }
      } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
        if(connection != null) {
          connection.releaseInterface(usbDeviceInterface);
          connection.close();
        }
        connection = null;
        usbDevice = null;
        endpointIn = null;
        endpointOut = null;
      }
    }
  };
 

我还尝试通过首先将操作名称添加到我的类变量中来向广播接收器添加 USB 权限侦听器:

private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

然后将操作添加到我的意图过滤器中,如下所示:

 public NativeUsbService(ReactApplicationContext reactContext) {
    // register device attached/detached event listeners
    IntentFilter filter = new IntentFilter();
    filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
    filter.addAction(ACTION_USB_PERMISSION); // added action to my intent filter

    reactContext.registerReceiver(usbReceiver, filter);
  }

最后对这个动作做出这样的反应:

  private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
        synchronized (this) {
          UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

          if(device != null){
            usbDevice = device;
          } 
        }
      } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
        Log.d(TAG, "onReceive: Device was detached!");
        if(connection != null) {
          connection.releaseInterface(usbDeviceInterface);
          connection.close();
        }
        connection = null;
        usbDevice = null;
        endpointIn = null;
        endpointOut = null;

        sendEvent("onDeviceDetached", true);
      }
      else if (action.equals(ACTION_USB_PERMISSION)) {
        Log.d(TAG, "onReceive: ACTION_USB_PERMISSION");
        if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
          Log.d(TAG, "onReceive: EXTRA_PERMISSION_GRANTED = true");
        } else Log.d(TAG, "onReceive: EXTRA_PERMISSION_GRANTED = false");
      }
    }
  };

请让我知道任何缺失的信息。 任何帮助是极大的赞赏。


回答我自己的问题以防其他人面临同样的问题。

我想在授予权限后再次手动请求权限,因为当用户按下对话框中的选项时可以处理此手动权限请求。我放弃了这个想法,不是因为它不起作用,而是因为我认为用户没有必要在初始(自动对话框)之后按下另一个对话框。 我必须补充一点,我还没有实现这个解决方案,所以我不确定它是否会再次提示用户,但我之前在手动权限请求方面遇到了麻烦。如果您想尝试这种方法,该方法属于 UsbManager 类,并且像这样调用usbManger.requestPermission(usbDevice).

我最终得到了一个解决方案,我启动一个运行循环调用的线程usbManager.hasPermission(usbDevice)直到它获得许可,然后发出一个事件(发出这个事件是我的用例,按照你喜欢的方式实现它)。

解决方案可以在这里看到:

  import android.hardware.usb.UsbDevice;
  import android.hardware.usb.UsbDeviceConnection;
  import android.hardware.usb.UsbManager;
  import com.facebook.react.bridge.ReactApplicationContext;
  ...

  private static volatile boolean permissionThreadShouldStop = false;
  private static Thread activePermissionThread = null;

  ...

  public static void usbPermissionEventEmitter(ReactApplicationContext reactContext, UsbManager usbManager, UsbDevice usbDevice) {

    if((activePermissionThread != null && activePermissionThread.isAlive())) {
      activePermissionThread.interrupt();
    }

    permissionThreadShouldStop = false;

    activePermissionThread = new Thread(new Runnable() {
      @Override
      public void run() {

        while (!usbManager.hasPermission(usbDevice) && !permissionThreadShouldStop) {
          try {
            Thread.sleep(30);
          } catch (InterruptedException e) {
            e.printStackTrace();
            break;
          }
        }

        if(usbManager.hasPermission(usbDevice)) {
          sendEvent(reactContext, "onUsbPermissionGranted", true);
        }
      }
    });

    activePermissionThread.start();
  }

The ReactApplicationContext可以与普通的 android 上下文交换。但这是针对 React Native 模块的,所以我使用了 ReactContext。

我希望这对某人有帮助,因为说实话,我真的很惊讶 Android 文档在使用 android.hardware.usb 库实现 USB 功能方面是多么的匮乏。 一般来说,在网上搜索信息时,我经常发现自己迷失了方向,因为关于这个主题的信息很少。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用“设备过滤器”解决方案时如何处理 Android 上的 USB 权限对话框事件? 的相关文章

  • 在 Android 中加密/解密字符串的简单方法

    我的问题是如何加密String String AndroidId Override public void onCreate Bundle savedInstanceState super onCreate savedInstanceSta
  • Jetpack Compose:制作全屏(绝对定位)组件

    我怎样才能在全屏渲染树的深处制作一个可组合的 类似于Dialog可组合作品 例如 当用户单击图像时 它会显示该图像的全屏预览 而无需更改当前路线 我可以用 CSS 来做到这一点position absolute or position fi
  • 无需递归即可对可观察结果进行分页 - RxJava

    我有一个非常标准的 API 分页问题 您可以通过一些简单的递归来处理 这是一个捏造的例子 public Observable
  • 如何在Android模拟器中隐藏应用程序图标?

    我有一个应用程序在启动完成后自动启动 但应用程序图标显示在android模拟器中 现在我想向用户隐藏该图标 这样用户就无法知道应用程序已启动 并且他们无法启动该应用程序手动申请 在您的 AndroidManifest xml 文件中 您可能
  • 双屏 Android Studio 中不显示自动补全

    我刚刚从 Eclipse 切换到 Android Studio IntelliJ 我不明白自动补全是如何工作的 我尝试了 Control Space Control Shift Space 但没有相关建议 不在 Java 文件中 也不在布局
  • Android Google Map V2:如何在单击另一个标记时更改先前单击的标记的图标

    更新 我通过添加 previousMarker 对象解决了性能问题 因此 只有先前单击的标记将被删除并替换为默认图标 但是 当我单击标记时 信息窗口仍然不显示 我有一个地图视图并在上面设置了一些标记 我想要的是 当我单击一个标记时 它将其图
  • Joshua Bloch 的构建器设计模式有何改进?

    早在 2007 年 我就读过一篇关于 Joshua Blochs 所采用的 构建器模式 的文章 以及如何修改它以改善构造函数和 setter 的过度使用 特别是当对象具有大量属性 其中大部分属性是可选的 时 本文对此设计模式进行了简要总结
  • Java 8 Stream,获取头部和尾部

    Java 8 引入了Stream http download java net jdk8 docs api java util stream Stream html类似于 Scala 的类Stream http www scala lang
  • 如何使用 Jersey 将嵌套列表封送为 JSON?我得到一个空数组或一个包含数组的单元素字典数组

    我正在开发一个使用 Jersey 将对象转换为 JSON 的项目 我希望能够写出嵌套列表 如下所示 data one two three a b c 我想要转换的对象首先将数据表示为 gt gt 我认为 Jersey 会做正确的事情 以上输
  • TextView.setMaxLines 不起作用?

    在我的应用程序中 我有一个屏幕 其中显示一些文本 然后显示一张照片 文本的长度是可变的 有时根本没有 有时很多 所以我想对其进行设置 以便文本永远不会占用超过几行 但可以滚动 为下面的图像留下足够的空间 我这部分的视图组件是以编程方式创建的
  • java实现excel价格、收益率函数[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 即使禁用安全性,OAuth 令牌 API 也无法在 Elastic Search 中工作

    我是 Elastic search 新手 使用 Elastic search 版本 7 7 1 我想通过以下方式生成 OAuth 令牌弹性搜索文档 https www elastic co guide en elasticsearch re
  • Spring Data Rest 多对多 POST

    首先 让我解释一下我的用例 这非常简单 有一个用户实体和一个服务实体 我使用 UserService 作为连接实体 连接表 在用户和服务之间建立多对多关联最初 会有一些用户集和一些服务集 用户可以在任何时间点订阅任何服务 在这种情况下 将向
  • Selenium 单击在 Internet Explorer 11 上不起作用

    我尝试在 Internet Explorer 上单击 selenium 但它不起作用 我努力了element click moveToElement element click build perform javascript没事了 事实上
  • 动态更改按钮上的图像视图

    在我的应用程序中 我有按钮和ImageView 当我按下按钮时我想改变ImageView 我的可绘制文件夹中有 5 张图像 按下按钮时 ImageView 根据按钮单击一张一张地更改图像 我想要它的解决方案 感谢任何可以提供帮助的人 维护一
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据
  • 使用 DBCP 配置 Tomcat

    在闲置一段时间 几个小时 后 我们收到了 CommunicationsException 来自 DBCP 错误消息 在异常中 位于这个问题的末尾 但我没有看到任何配置文件中定义的 wait timeout 我们应该看哪里 在 tomcat
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样
  • 在会话即将到期之前调用方法

    我的网络应用程序有登录的用户 有一个超时 在会话过期之前 我想执行一个方法来清理一些锁 我已经实现了sessionListener但一旦我到达public void sessionDestroyed HttpSessionEvent eve
  • GAE 无法部署到 App Engine

    我正在尝试从 Eclipse 发布 Web 应用程序 我在 GAE 上创建了四个项目 可以通过登录我的帐户并查看控制台来查看它们 我已经改变了appengine web xml到项目的应用程序 ID 如果我将其更改为 GAE 上第一个创建的

随机推荐