Android:连接USB设备,等待许可

时间:2015-04-24 18:18:38

标签: java android permissions usb

我尝试这样做:连接到USB设备并获得打开(或失败)的连接。我根据我发现的例子和解释做了逻辑,但是我在等待许可授予方面遇到了问题。首先,我尝试了一个好的"使用wait()+ notifyAll()的方式,比我尝试使用检查的直接循环,但是两次等待方法(waitConnection())都阻塞了我给它的超时,并且只有在收到消息之后。所以我尝试了这两个版本。

  1. 等待/ notifyAll的:

    public UsbConnector startConnection(Context context) {
    
    BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (syncObj) {
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (device != null) {
                            if (device.getVendorId() == vendorId && device.getProductId() == productId) {
                                connection = usbManager.openDevice(device);
                                connectedDevice = device;
                            }
                        }
                    }
                    syncObj.notyfyAll();
                }
            }
        }
    };
    
    try {
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        for (final UsbDevice device : usbManager.getDeviceList().values()) {
            if (device.getVendorId() == this.vendorId && device.getProductId() == this.productId) {
    
                context.registerReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION));
                usbManager.requestPermission(device,
                        PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0));
                break;
            }
        }
    } catch (Exception e) {
    }
    return this;
    }
    
    public UsbDeviceConnection waitConnection(int timeout) {
    try {
        Thread.sleep(10, 0);
        syncObj.wait(timeout);
    } catch (InterruptedException e) {
    }
    return getConnection();
    }
    
  2. 直接循环

    public UsbConnector startConnection(Context context) {
    
    BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (device != null) {
                            if (device.getVendorId() == vendorId && device.getProductId() == productId) {
                                connection = usbManager.openDevice(device);
                                connectedDevice = device;
                            }
                        }
                    }
                    permissionRequested = false;
                }
            }
        }
    };
    
    try {
        permissionRequested = false;
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        for (final UsbDevice device : usbManager.getDeviceList().values()) {
            if (device.getVendorId() == this.vendorId && device.getProductId() == this.productId) {
    
                permissionRequested = true;
                context.registerReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION));
                usbManager.requestPermission(device,
                        PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0));
                break;
            }
        }
    } catch (Exception e) {
    }
    return this;
    }
    
    public UsbDeviceConnection waitConnection(int timeout) {
    int waited = timeout;
    while (permissionRequested && waited > 0) {
        try {
            Thread.sleep(10, 0);
        } catch (InterruptedException e) {
        }
        waited -= 10;
    }
    
    return getConnection();
    }
    
  3. 所以在这两种情况下,根据日志,waitConnection()方法(在startConnection()之后立即被消费者调用)似乎阻止执行(我给它超时10秒,它被阻止了10秒),只有在它完成后,BroadcastReceiver才会收到消息。似乎requestPermission()不是异步(我认为是),但在这种情况下,startConnection()如何在接收到消息之前立即退出?我如何等待BroadcastReceiver获取消息?假设我不使用waitConnection()方法,我的消费者应该如何知道它何时可以开始检查连接可用性?

1 个答案:

答案 0 :(得分:0)

“并且只有在完成后,BroadcastReceiver才会收到消息”

默认情况下,onReceived回调在主线程上调用。听起来你也在主线程上调用waitConnection()。由于waitConnection()阻塞,主线程在waitConnection()返回之前无法处理任何其他消息。这意味着在onReceived超时之前不会调用waitConnection()

阻止主线程通常是一个坏主意。 Read here

相反,您可以onReceive启动一项新活动,然后在获得USB许可后执行您需要执行的操作。这对你来说可能是也可能不是最好的解决方案,但无论如何,这里的关键是永远不要阻止主线程。