Android 7.1.2下USB权限请求广播未触发,弹窗反复弹出问题排查
问题原因分析
1. 主线程阻塞导致广播无法处理
如果你的while(true)循环加Thread.sleep(1000)是在**主线程(UI线程)**执行的,会直接阻塞主线程。Android系统中,BroadcastReceiver的onReceive方法默认在主线程运行,主线程被阻塞后,完全无法处理权限请求的回调广播,导致mUsbReceiver永远不会被触发。同时,因为主线程卡死,usbManager.hasPermission(usbDevice)始终返回false,循环会反复调用requestPermission,造成权限弹窗持续弹出。
Android 10及以上版本对主线程阻塞有更严格的监控和优化,或者你的代码在这些版本中是在子线程执行的,所以没有出现问题,但Android 7.1.2无此类优化,阻塞主线程直接导致广播处理失效。
2. PendingIntent的Flag设置问题
在Android 7.1.2(API 25)及以下版本中,PendingIntent.getBroadcast使用0作为flag,会导致PendingIntent无法正确更新或传递广播。旧版本系统对PendingIntent的复用逻辑更严格,多次调用requestPermission时,复用的PendingIntent无法触发广播接收器。
3. 动态广播注册的调度失效
虽然你注册了广播接收器,但主线程被阻塞后,系统无法完成接收器的注册流程,或者注册后的接收器无法被系统调度执行,这也会导致onReceive不被触发。
修复方案
- 将权限请求逻辑移到子线程:避免阻塞主线程,让主线程能正常处理广播回调。
- 修改PendingIntent的Flag:使用
PendingIntent.FLAG_UPDATE_CURRENT替代0,确保每次请求都能正确传递广播。 - 移除无限轮询:改用广播回调处理权限结果,不需要循环判断
hasPermission。
修复后的核心代码示例:
private final String ACTION_USB_PERMISSION = "com.myapp.USB_PERMISSION"; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); log(Log.INFO, TAG, "on intent received >" + intent.getAction()); if (ACTION_USB_PERMISSION.equals(action)) { log(Log.INFO, TAG, "On receive for usb permission"); synchronized (this) { UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { log(Log.INFO, TAG, "Usb connection permission accepted"); if (device != null) { log(Log.INFO, TAG, "usb connection devices"); // 处理权限通过后的逻辑 } else { log(Log.INFO, TAG, "No usb connection devices"); } } else { log(Log.INFO, TAG, "Usb connection permission denied"); UIHelper.showToastLong("Usb permission is needed to use the USB Device", activity); } // 权限处理完成后注销接收器(按需操作) context.unregisterReceiver(this); } } } }; // 在子线程发起权限请求 new Thread(() -> { UsbManager usbManager = (UsbManager) activity.getSystemService(Context.USB_SERVICE); if (usbManager.hasPermission(usbDevice)) { // 已有权限,直接处理逻辑 return; } PendingIntent permissionIntent = PendingIntent.getBroadcast(activity, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_UPDATE_CURRENT); activity.registerReceiver(mUsbReceiver, new IntentFilter(ACTION_USB_PERMISSION)); usbManager.requestPermission(usbDevice, permissionIntent); }).start();
内容的提问来源于stack exchange,提问作者Nimila Hiranya
相关产品推荐
相关产品推荐

