You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中USB权限请求的PendingIntent未触发问题

USB权限请求后BroadcastReceiver未触发的解决方案

问题根源及修复步骤

1. 调整PendingIntent的标志位

Android 12(API 31)及以上版本中,PendingIntent.FLAG_IMMUTABLE会阻止系统向Intent中写入权限结果(UsbManager.EXTRA_PERMISSION_GRANTED)、设备信息(UsbManager.EXTRA_DEVICE)等额外数据,导致Receiver无法正确解析广播内容。

修改PendingIntent创建代码:

val permissionIntent = PendingIntent.getBroadcast(
    this,
    0,
    Intent(ACTION_USB_PERMISSION), 
    // 适配不同版本的标志位
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        PendingIntent.FLAG_MUTABLE
    } else {
        PendingIntent.FLAG_UPDATE_CURRENT
    }
)

2. 调整Receiver注册与权限请求的顺序

当前代码先发起权限请求、后注册Receiver,会导致系统发送权限结果广播时,Receiver尚未完成注册,无法接收广播。

将Receiver注册代码移至权限请求之前:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    usbReceiver = UsbBroadcastReceiver()
    
    // 先注册广播接收器
    val filter = IntentFilter().apply {
        addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
        addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
        addAction(ACTION_USB_PERMISSION)
    }
    registerReceiver(usbReceiver, filter, RECEIVER_NOT_EXPORTED)
    
    // 再创建PendingIntent并发起权限请求
    val permissionIntent = PendingIntent.getBroadcast(
        this,
        0,
        Intent(ACTION_USB_PERMISSION), 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.FLAG_MUTABLE
        } else {
            PendingIntent.FLAG_UPDATE_CURRENT
        }
    )
    
    val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
    usbManager.deviceList.values.forEach { device ->
        if (!usbManager.hasPermission(device)) {
            Log.d("USB_REQUEST", "Requesting permission for device: ${device.deviceName}")
            usbManager.requestPermission(device, permissionIntent)
        }
    }
    
    setContent {
        SampleTestAppTheme {
            Scaffold { innerPadding ->
                Box(
                    modifier = Modifier
                        .padding(innerPadding)
                        .fillMaxSize()
                ) {
                    Text("USB Communication Example", modifier = Modifier.padding(16.dp))
                }
            }
        }
    }
}

3. 确保ACTION_USB_PERMISSION的一致性(可选验证)

将自定义Action提取为全局常量,避免拼写不一致导致的广播匹配失败:

// 全局常量定义
const val ACTION_USB_PERMISSION = "${BuildConfig.APPLICATION_ID}.USB_PERMISSION"

class MainActivity : ComponentActivity() {
    // 直接使用全局常量
}

class UsbBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            ACTION_USB_PERMISSION -> {
                // 权限结果处理逻辑
            }
            // 其他Action处理
        }
    }
}

4. 补充Manifest配置(针对设备插拔监听)

如果需要稳定监听设备插拔事件,可在Manifest中为Receiver添加静态配置(动态注册也生效,但静态注册需指定设备过滤):

<receiver android:name=".UsbBroadcastReceiver"
          android:exported="false">
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
        <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
    </intent-filter>
    <!-- 如需指定特定设备,添加设备过滤xml -->
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
               android:resource="@xml/device_filter"/>
</receiver>

内容的提问来源于stack exchange,提问作者sharathraj.a s.k.m

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:15:56