Android应用无法接收UsbManager.ACTION_USB_DEVICE_DETACHED事件求助
问题分析与解决方案
核心问题
Android系统对USB_DEVICE_DETACHED事件的处理逻辑和USB_DEVICE_ATTACHED不同:
USB_DEVICE_ATTACHED可以通过Manifest中的intent-filter直接唤起ActivityUSB_DEVICE_DETACHED仅会发送给已持有对应设备权限且动态注册了广播接收器的组件,Manifest注册的该事件intent-filter无法自动唤起Activity
解决方案:后台Service监听+动态广播
通过后台Service持续监听USB分离事件,收到事件后主动唤起SetupPrinterActivity,具体步骤如下:
1. 调整AndroidManifest配置
移除Activity中无效的USB_DEVICE_DETACHED相关配置,新增后台Service:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- 原有权限、Feature配置保留 --> <application> <!-- 修改SetupPrinterActivity配置 --> <activity android:name=".ui.setupprinter.SetupPrinterActivity" android:exported="true" android:launchMode="singleInstance" android:screenOrientation="landscape" android:theme="@style/Theme.MyApp.NoActionBar"> <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" /> </activity> <!-- 添加USB监控Service --> <service android:name=".service.USBMonitorService" android:exported="false" android:foregroundServiceType="specialUse" /> </application> </manifest>
2. 创建USB监控Service
实现后台监听USB分离事件的Service:
class USBMonitorService : Service() { private lateinit var usbReceiver: BroadcastReceiver private lateinit var usbManager: UsbManager override fun onCreate() { super.onCreate() usbManager = getSystemService(USB_SERVICE) as UsbManager initReceiver() // 可选:启动为前台服务,避免被系统后台回收 startForeground(1, NotificationCompat.Builder(this, "USB_MONITOR_CHANNEL") .setContentTitle("USB设备监控") .setContentText("正在监听USB状态变化") .setSmallIcon(R.mipmap.ic_launcher) .build()) } private fun initReceiver() { usbReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { UsbManager.ACTION_USB_DEVICE_DETACHED -> { val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE) device?.let { // 唤起SetupPrinterActivity val launchIntent = Intent(context, SetupPrinterActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP } context?.startActivity(launchIntent) } } } } } val filter = IntentFilter().apply { addAction(UsbManager.ACTION_USB_DEVICE_DETACHED) } registerReceiver(usbReceiver, filter) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { return START_STICKY // 服务被系统杀死后自动重启 } override fun onDestroy() { super.onDestroy() unregisterReceiver(usbReceiver) } override fun onBind(intent: Intent?): IBinder? { return null } }
3. 在SetupPrinterActivity中启动Service
确保USB设备连接后启动监控Service,同时处理权限请求(必须持有设备权限才能收到分离事件):
class SetupPrinterActivity : AppCompatActivity() { private lateinit var usbManager: UsbManager private var usbReceiver: BroadcastReceiver? = null private val permissionReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if ("com.your.package.USB_PERMISSION" == intent?.action) { val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE) if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { device?.let { // 权限获取成功,启动监控服务 startService(Intent(context, USBMonitorService::class.java)) onUSBAttach(it.deviceName) } } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) usbManager = getSystemService(USB_SERVICE) as UsbManager initReceiver() registerReceiver(permissionReceiver, IntentFilter("com.your.package.USB_PERMISSION")) // 处理USB设备连接事件的权限请求 intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)?.let { device -> val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent("com.your.package.USB_PERMISSION"), PendingIntent.FLAG_IMMUTABLE) usbManager.requestPermission(device, permissionIntent) } } // 原有initReceiver方法保留,仅处理Activity存活时的事件回调 private fun initReceiver() { usbReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { try { when (intent?.action) { UsbManager.ACTION_USB_DEVICE_ATTACHED -> { val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE) device?.let { onUSBAttach(it.deviceName) } } UsbManager.ACTION_USB_DEVICE_DETACHED -> { val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE) device?.let { onUSBDetach(it.deviceName) } } } } catch (e: Exception) { Log.e("CHKI", "BroadcastReceiver异常: ${e.message}") e.printStackTrace() } } } val filter = IntentFilter().apply { addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED) addAction(UsbManager.ACTION_USB_DEVICE_DETACHED) } registerReceiver(usbReceiver, filter) } override fun onDestroy() { super.onDestroy() usbReceiver?.let { unregisterReceiver(it) } unregisterReceiver(permissionReceiver) } // 原有onUSBAttach、onUSBDetach方法保留 private fun onUSBAttach(deviceName: String) { /* ... */ } private fun onUSBDetach(deviceName: String) { /* ... */ } }
关键说明
- 必须获取对应USB设备的访问权限,否则Service无法收到该设备的
USB_DEVICE_DETACHED广播 - 前台服务模式可根据需求调整,若不需要持续监控,可在设备分离后停止服务
- 启动Activity时使用
FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_SINGLE_TOP确保页面正确唤起且不重复创建
内容的提问来源于stack exchange,提问作者ankushlokhande
相关产品推荐
相关产品推荐

