【问题标题】:Android USB Permissions, onPause, onResume - Unfortunately, System UI has stopped"Android USB 权限、onPause、onResume - 不幸的是,系统 UI 已停止”
【发布时间】:2014-04-28 03:47:16
【问题描述】:

我正在使用 Android Studio 0.5.2 开发一个 Android 应用程序。

我的应用程序正在运行一个看似正常运行的 USB 主机 - 除非在应用程序启动时设备已连接(并且尚未授予权限)。

一般来说,当 USB 连接时(应用程序运行时)会发生什么:

  • “onResume”被调用 - 这会检测设备并请求许可。创建一个意图过滤器以捕获 USB 连接、分离或授予权限

  • 显示权限请求,选择确定

  • “onResume”再次被调用。这个函数的第一行是“super.onResume()”

  • 只要我越过 super.onResume,就会显示“不幸的是,系统 UI 已停止”消息并且 Android UI 崩溃

  • 我的应用程序继续正常工作

如果我在应用程序已经运行时连接设备,则没有问题 - 这仅在启动时连接 USB 时发生。

任何有关可能导致此问题的原因或如何进一步缩小问题范围的见解将不胜感激。我在下面附上了值得注意的代码。我通常不是 Java 开发人员,所以我怀疑这个问题与暂停/恢复行为、接收器、意图过滤器或权限有关。

// *************************************************************
// ************************* USB Stuff *************************
// *************************************************************
boolean resumePermissionBlocked = false;
PendingIntent pendingIntent = null;
BroadcastReceiver receiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        // Get the information about what action caused this event
        try {
            String action = intent.getAction();
            Log.i(TAG, "$EC: action:" + action);

            if ("com.android.example.USB_PERMISSION".equals(action)) {
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {


                        if (device.getProductId() == 0xAAAA) {
                            if (device.getVendorId() == 0xBBBB) {
                                // see if we have permission
                                UsbManager openManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

                                // send a message to the worker thread to begin opening a connection to this device
                                ThreadMsg msg = new ThreadMsg();
                                msg.request = MsgRequest.openConnection;
                                msg.objectA = device;
                                msg.objectB = openManager;
                                sendMessageToWorker(msg);

                            }
                        }
                    }
                } else {
                    if (device != null)
                        Log("USB Permission denied", TextFormat.StrongWarning_withTime);
                }
            }
            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device == null) return;
                if (device.getProductId() == 0x003C) {
                    if (device.getVendorId() == 0x04D8) {
                        // see if we have permission
                        UsbManager openManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
                        if (!openManager.hasPermission(device)) {
                            resumePermissionBlocked = true; // block the resume function from trying to re-ask for permission
                            openManager.requestPermission(device, mPermissionIntent);
                            return;
                        }
                        ThreadMsg msg = new ThreadMsg();
                        msg.request = MsgRequest.openConnection;
                        msg.objectA = device;
                        msg.objectB = openManager;
                        sendMessageToBootloader(msg);
                    }
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                // If it was a USB device detach event, then get the USB device
                // that caused the event from the intent.
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                ThreadMsg msg = new ThreadMsg();
                msg.request = MsgRequest.closeConnection;
                msg.objectA = device;
                sendMessageToBootloader(msg);
            }
        } catch (Exception e) {
            Log.i(TAG, "onResume catch: " + e.toString());
        }
    }

};

boolean receiverHasBeenRegistered = false;

PendingIntent mPermissionIntent;
@Override
public void onResume(){
    try {

        super.onResume();

        if (resumePermissionBlocked) {
            // this was resumed from a permission request - don't try to connect to the device now, leave it for the USB_PERMISSION_GRANTED intent
            resumePermissionBlocked = false;    // clear the flag
        } else {
            UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
            HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
            if (deviceList != null) {
                Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
                Log.i(TAG, "$EC: Begin iteration");

                while (deviceIterator.hasNext()) {
                    // Is this the device we are after?
                    UsbDevice device = deviceIterator.next();
                    if (device == null) return;
                    if (device.getProductId() == 0xAAAA) {
                        if (device.getVendorId() == 0xBBBB) {
                            // see if we have permission
                            UsbManager openManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
                            if (!openManager.hasPermission(device)) {
                                resumePermissionBlocked = true;         // block the subsequent call to this (between the application resuming and permission being granted)
                                openManager.requestPermission(device, mPermissionIntent);
                                return;
                            }
                            ThreadMsg msg = new ThreadMsg();
                            msg.request = MsgRequest.openConnection;
                            msg.objectA = device;
                            msg.objectB = openManager;
                            sendMessageToWorker(msg);
                        }
                    }
                }
            }
        }
    } catch (Exception e)
    {
        Log.i(TAG, "onResume catch: " + e.toString());
    }

    if (!receiverHasBeenRegistered) {
        // this line is for permissions
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.android.example.USB_PERMISSION"), 0);

        //Create a new filter to detect USB device events
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction("com.android.example.USB_PERMISSION");
        registerReceiver(receiver, filter);
        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(getPackageName() + ".USB_PERMISSION"), 0);
        receiverHasBeenRegistered = true;
    }
}

@Override
public void onPause() {
    /* unregister any receivers that we have */
    try {
        if (receiver != null && receiverHasBeenRegistered) {
            unregisterReceiver(receiver);
            receiverHasBeenRegistered = false;
        }
    } catch (Exception e) {
        // if this happens, then the receiver was probably never registered in the first place
        Log.i(TAG, "onPause catch: " + e.toString());
    }
    super.onPause();
}

【问题讨论】:

    标签: java usb android-studio intentfilter android-permissions


    【解决方案1】:
    1. 在 onResume 方法结束时尝试 super.onResume
    2. 在应用程序启动时提醒用户连接 USB 设备(主要活动的 onCreate)如果设备未连接,则发出警报消息并完成/关闭 主要活动
    3. 在清单文件中添加意图过滤器,允许应用在连接设备时自动启动
    4. 当 UI 停止消息出现时,尝试捕获异常 printstacktrack 显示并从异常进一步调试。
    5. 确保遵循 android 文档中的步骤 https://developer.android.com/guide/topics/connectivity/usb/host.html

    【讨论】:

      猜你喜欢
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 1970-01-01
      • 2016-12-12
      • 2013-12-11
      • 1970-01-01
      • 2012-08-19
      相关资源
      最近更新 更多