Android 12下USB OTG权限广播接收器返回值始终为false求助
USB权限授权后返回false的解决方案
针对你的Android USB应用在高版本系统(Android 11+)中,点击权限授权后UsbManager.EXTRA_PERMISSION_GRANTED始终返回false的问题,以下是核心原因和解决办法:
核心原因:Immutable PendingIntent限制
在Android 12(API 31)及以上版本,你使用了PendingIntent.FLAG_IMMUTABLE创建权限请求的PendingIntent,但UsbManager.requestPermission()需要向PendingIntent对应的Intent中写入权限结果数据,而Immutable类型的Intent不允许被修改,导致系统无法传递授权结果,最终返回默认的false。
解决方案
1. 修改PendingIntent的Flags配置
将SDK31+的Flags改为FLAG_MUTABLE,确保系统能向Intent中写入权限结果:
int pendingFlags; if(Build.VERSION.SDK_INT >= 31) { // 使用FLAG_MUTABLE替代FLAG_IMMUTABLE pendingFlags = PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT; } else { pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT; }
2. 完善Manifest配置
确保Manifest中声明USB Host功能,并添加设备过滤规则,让系统正确识别CP2102设备:
声明USB Host功能
在Manifest根节点添加:
<uses-feature android:name="android.hardware.usb.host" android:required="true" />
添加设备过滤的Intent-Filter
在对应的Activity标签内添加:
<intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
创建设备过滤配置文件
在res/xml目录下新建device_filter.xml,配置CP2102的VID和PID(标准CP2102的VID为10C4,PID为EA60):
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="10C4" product-id="EA60" /> </resources>
3. 优化权限请求逻辑
在请求权限前先检查是否已拥有权限,避免重复请求:
if(device != null) { if(usbManager.hasPermission(device)) { // 已拥有权限,直接初始化USB if(usb.InitUSB(intent, 0)) { Log.d("DEBUG", "USB Initialized"); } else { Log.d("DEBUG", "USB Init Failed."); } } else { Log.d("DEBUG", "Getting Permission"); usbManager.requestPermission(device, pendingIntent); } }
4. 确保广播注册的生命周期管理
动态注册的广播接收器建议在onResume()中注册,onPause()中注销,避免内存泄漏:
@Override public void onResume() { super.onResume(); // 注册广播接收器 getContext().registerReceiver(broadcastReceiver, attatchIntentFilter); getContext().registerReceiver(broadcastReceiver, detatchIntentFilter); getContext().registerReceiver(broadcastReceiver, permissionIntentFilter); } @Override public void onPause() { super.onPause(); // 注销广播接收器 getContext().unregisterReceiver(broadcastReceiver); }
内容的提问来源于stack exchange,提问作者JP Hayes
相关产品推荐
相关产品推荐

