安卓工控常见问题汇总闪退、后台被杀、外设权限不足、U 盘挂载失败工控开发三年代码没写几行填坑倒是填出一身腱子肉。今天就把我踩过的、见过的、替人擦过屁股的所有坑按类型列个刑场清单——对照着排查少走三年弯路。一、APP 闪退排查三板斧闪退是工控最常见的死亡画面排查遵循三步法1.1 抓日志# 实时抓取崩溃日志adb logcat|grep-EAndroidRuntime|FATAL# 导出到文件adb logcat-dcrash.log1.2 常见闪退原因 修复崩溃类型典型日志关键字根因修复NullPointerExceptionNullPointerException串口读取返回 null 直接用了加if (data ! null)空判断权限缺失SecurityException没声明或没动态申请权限AndroidManifest 加权限 运行时申请FileNotFoundException文件未找到/dev/ttyS1节点不存在检查设备树配置确认串口编号UnsatisfiedLinkErrorso 库加载失败abi 不匹配armeabi-v7a vs arm64ndk.abiFilters 对齐芯片架构NetworkOnMainThread主线程网络主线程直接 http 请求丢到子线程或用 Retrofit 异步1.3 崩溃后自动重启守护// 全局异常捕获Thread.setDefaultUncaughtExceptionHandler((t,e)-{// 写日志到文件logCrashToFile(e);// 延迟 1 秒杀掉进程让系统重启 Activityandroid.os.Process.killProcess(android.os.Process.myPid());});二、后台 Service 被杀 / 保活失效这是工控开发的心头大恨——跑得好好的采集服务一觉醒来没了。2.1 被杀原因链系统内存不足 → LowMemoryKiller 打分 → 非前台进程优先被杀 ↓ Doze 模式激活 → 限制后台计算/网络 → Service 被暂停 ↓ 电池优化 → 白名单未添加 → 系统强制停止2.2 保活方案从弱到强// 1. 前台 Service — 最低要求NotificationnotificationnewNotificationCompat.Builder(this,CHANNEL_ID).setContentTitle(数据采集运行中).setSmallIcon(R.drawable.ic_service).build();startForeground(1,notification);// 2. 加入电池优化白名单IntentintentnewIntent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);intent.setData(Uri.parse(package:getPackageName()));startActivity(intent);// 3. 双进程守护极端方案内存开销大// Service A 被杀的 onDestroy 中重启 Service B// Service B 同样守护 Service A实际建议工控设备做好三件事即可——前台 Service电池白名单AlarmManager 定时唤醒检查。不要搞双进程那是手机 App 的歪门邪道。// AlarmManager 兜底每 5 分钟检查采集服务是否存活publicclassServiceGuardReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Contextcontext,Intentintent){if(!isServiceRunning(context,CollectService.class)){context.startService(newIntent(context,CollectService.class));}}}三、串口 / USB 外设权限不足工控外设串口、USB 摄像头、RFID 读卡器经常卡在权限这一步。3.1 串口权限/dev/ttyS*默认是 root:root 权限普通 App 无权读写。解决方案# 方案 Ainit.rc 中改权限需要系统签名chmod0666 /dev/ttyS1# 方案 BApp 以系统应用身份运行# 把 apk 放到 /system/priv-app/ 下共享系统 UID!-- AndroidManifest.xml --manifestxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:sharedUserIdandroid.uid.systempackagecom.alspd.collector3.2 USB 设备权限// 动态申请 USB 权限UsbManagerusbManager(UsbManager)getSystemService(USB_SERVICE);PendingIntentpiPendingIntent.getBroadcast(this,0,newIntent(ACTION_USB_PERMISSION),PendingIntent.FLAG_IMMUTABLE);HashMapString,UsbDevicedeviceListusbManager.getDeviceList();for(UsbDevicedevice:deviceList.values()){usbManager.requestPermission(device,pi);}!-- 声明要获取哪些 USB 设备的权限 --intent-filteractionandroid:nameandroid.hardware.usb.action.USB_DEVICE_ATTACHED//intent-filtermeta-dataandroid:nameandroid.hardware.usb.action.USB_DEVICE_ATTACHEDandroid:resourcexml/device_filter/device_filter.xml?xml version1.0 encodingutf-8?resources!-- 匹配所有 USB 设备简化版生产环境应指定 VID/PID --usb-device//resources四、U 盘挂载失败工控设备插 U 盘导数据是高频操作挂载失败常见原因4.1 vold 机制问题Android 的voldVolume Daemon负责自动挂载外部存储。挂载失败排查# 1. 检查是否识别到设备ls/dev/block/sd*# U盘设备节点dmesg|grep-iusb# 内核日志# 2. 查看挂载状态mount|grep/mnt/media_rw# 3. 手动挂载mkdir-p/mnt/usb_storagemount-tvfat /dev/block/sda1 /mnt/usb_storage4.2 文件系统格式支持文件系统Android 默认支持备注FAT32支持最通用单文件 ≤ 4GBexFATAPI 24 原生U 盘推荐格式NTFS需第三方驱动需要 ntfs-3g 或修改 kernelext4支持Linux 原生Windows 不认4.3 代码读取 U 盘路径// 获取所有挂载的存储路径StorageManagersm(StorageManager)getSystemService(STORAGE_SERVICE);ListStorageVolumevolumessm.getStorageVolumes();for(StorageVolumevol:volumes){if(vol.isRemovable()){// 可移动设备Stringpathvol.getDirectory().getAbsolutePath();scanFiles(path);}}五、开机自启失效receiverandroid:name.BootReceiverandroid:exportedtrueintent-filteractionandroid:nameandroid.intent.action.BOOT_COMPLETED//intent-filter/receiver失效原因App 安装在 SD 卡BOOT_COMPLETED 广播在 SD 卡挂载前发出App 收不到。解决android:installLocationinternalOnly用户从未打开过 AppAndroid 3.1 要求 App 至少启动一次才能收到广播处于 stopped 状态被系统禁用自启部分定制 ROM 有自启管理需引导用户添加白名单六、其他高频问题速查问题原因解决ANR主线程 IO / 网络操作用 StrictMode 检测耗时操作丢子线程网络断连WiFi 弱信号无自动重连实现重连机制ConnectivityManager监听 指数退避重试屏幕旋转重建Activity 被 destroyrecreateconfigChangesorientation|screenSize或 ViewModel 保存内存泄漏静态持有 Context 等LeakCanary 集成检测多版本兼容API 行为差异Build.VERSION.SDK_INT 判断分别处理七、工控调试技巧总结# 一行命令查看设备关键信息adb shellcat /proc/version; echo ---; cat /proc/meminfo | head -5; echo ---; df -h; echo ---; logcat -d -t 50# 实时监控 CPUadb shelltop-n1|head-10# 查看 App 是否运行adb shellps|grepcom.alspd# 强制关闭 Appadb shell am force-stop com.alspd.collector# 模拟发送广播测试开机自启adb shell am broadcast-aandroid.intent.action.BOOT_COMPLETED工控开发没有银弹只有一本越写越厚的踩坑笔记。打印日志是这个行业最朴素的哲学——日志打得勤Bug 找得快老板笑得开。