Android AOA模式USB通信:重启APP后接收线程失效问题
Android AOA模式重启APP后无法接收PC数据的解决方案
采用AOA模式与PC通信的Android应用,关闭重启后设备能向PC发送数据,但监听线程无法接收,仅能通过重新插拔USB恢复。排查发现重启后附件已开启,但输入流处于异常状态导致PC发送超时。
核心问题分析
- 资源释放不彻底:关闭附件时未确保读取协程完全终止,且未清空附件引用,导致重新初始化时出现资源冲突
- 协程取消逻辑不完善:未处理协程取消时的异常,且
isReading状态未及时更新,导致线程残留 - 初始化时未清理旧资源:重新打开附件前未确保之前的流、文件描述符等完全释放
解决方案及修改代码
1. 完善资源清理逻辑(修改closeAccessory函数)
确保协程完全终止,清空所有相关引用:
fun closeAccessory() { // 先终止读取循环 isReading = false // 取消并等待协程结束,避免资源竞争 if (::readjob.isInitialized) { readjob.cancel() runBlocking { readjob.join() } } // 关闭输入流 try { mInputStream?.close() } catch (e: IOException) { Log.i(TAG, "Error closing inputStream", e) logInfo(TAG, "Error closing inputStream") } finally { mInputStream = null } // 关闭输出流 try { mOutputStream?.close() } catch (e: IOException) { Log.i(TAG, "Error closing outputStream", e) logInfo(TAG, "Error closing outputStream") } finally { mOutputStream = null } // 关闭文件描述符 try { mFileDescriptor?.close() } catch (e: IOException) { Log.i(TAG, "Error closing fileDescriptor", e) logInfo(TAG, "Error closing fileDescriptor") } finally { mFileDescriptor = null } // 清空附件引用 mAccessory = null }
2. 优化初始化逻辑(修改openAccessory函数)
初始化前先清理旧资源,处理协程取消异常,优化读取逻辑:
private fun openAccessory(accessory: UsbAccessory) { // 初始化前确保旧资源完全清理 closeAccessory() mFileDescriptor = usbManager.openAccessory(accessory) if (mFileDescriptor != null) { mAccessory = accessory val fd = mFileDescriptor!!.fileDescriptor mInputStream = FileInputStream(fd) mOutputStream = FileOutputStream(fd) logInfo(Companion.TAG, "Accessory opened") readjob = GlobalScope.launch(Dispatchers.IO) { isReading = true try { while (isReading) { val buffer = ByteArray(1000) val readBytes = mInputStream!!.read(buffer) // 仅处理实际读取到的数据,避免无效操作 if (readBytes > 0) { getIncomingData(buffer.copyOf(readBytes)) logInfo(Companion.TAG, "Read $readBytes bytes successfully") } } } catch (e: IOException) { logInfo(Companion.TAG, "Read failed: $e") } catch (e: CancellationException) { // 协程正常取消,无需报错 logInfo(Companion.TAG, "Read job cancelled") } finally { isReading = false // 异常或取消时自动清理资源 closeAccessory() } } } else { logInfo(Companion.TAG, "Accessory open fail") } }
额外检查项
- 确认AndroidManifest中已声明AOA相关配置:
<uses-feature android:name="android.hardware.usb.accessory" /> <intent-filter> <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/accessory_filter" /> - 确保USB附件广播接收器正确处理连接/断开事件,避免重复初始化或资源泄漏
内容的提问来源于stack exchange,提问作者Egepa
相关产品推荐
相关产品推荐

