ADB 与调试工具深度解析——跨平台开发者的 Android 调试利器
面试高频:ADB 的 C/S 架构、无线调试、logcat 过滤、dumpsys 与 bugreport 怎么用,以及热重载失败、ANR/crash 的现场排查思路。
一句话概括
ADB(Android Debug Bridge)是连接你和 Android 设备的万能桥——它既是设备管理器、又是日志服务器、还是调试通道。框架的 flutter run/react-native run-android 背后都在调它,一旦封装层给不出诊断信息,你就得直接上 ADB。
核心结论:掌握 devices、logcat、forward/reverse、dumpsys、bugreport 这五件套,就能脱离 Android Studio 独立定位绝大多数真机问题。 它不挑框架,Flutter/RN/鸿蒙最终都跑在 Android 上。
核心知识点
1. ADB 架构与连接:C/S 模型
ADB 由三部分组成:你敲的 Client、本机后台的 Server(管理设备通信)、设备上的 adbd(守护进程)。所以它能走 USB,也能走 TCP/IP 远程连设备。
1
2
3
4
5
6
7
8
# macOS 装 platform-tools
brew install android-platform-tools
adb --version
# 设备连不上时,重启 server 能解决八成问题
adb kill-server && adb start-server
adb devices
# 状态:device 正常 / offline 需重启 / unauthorized 手机上点"允许"
1
2
3
4
5
6
7
# Android 11+ 无线调试:先配对再连接(开发者选项→无线调试里给端口)
adb pair 192.168.1.50:37000 # 输入配对码
adb connect 192.168.1.50:39777
# Android 10 及以下:USB 状态下切 TCP,再连 IP
adb tcpip 5555
adb connect 192.168.1.50:5555
// ❌ 多装了一份 platform-tools,两个 adb server 抢 5037 端口,flutter 连不上设备 // ✅ 只留一份 adb,冲突时 adb kill-server 后让框架重新拉起
2. 安装卸载与多设备
1
2
3
4
5
6
adb install -r app.apk # -r 覆盖安装保留数据
adb install -t app.apk # -t 允许装 testOnly 的 debug 包
adb uninstall com.example.app # 卸载
adb uninstall -k com.example.app# 保留数据目录
adb -s emulator-5554 shell ... # 多设备时用 -s 指定序列号
找不到包名时:adb shell pm list packages | grep 关键词,或从当前界面反查 adb shell dumpsys window | grep mCurrentFocus。
3. logcat:日志过滤是基本功
Android 日志级别(由低到高):V < D < I < W < E < F(还有 A/Assert,极少用)。adb logcat 默认刷全量,必须会过滤。
1
2
3
4
5
adb logcat -c # 清历史
adb logcat *:E # 只看 Error 及以上
adb logcat -s flutter:V ReactNativeJS:V *:S # 只看指定 tag,其他静默
adb logcat --pid=$(adb shell pidof com.example.app) # 按进程过滤
adb logcat -v time > app.txt # 带时间戳落盘,崩了再搜 FATAL EXCEPTION
1
2
# 抓原生层崩溃与 Flutter 引擎错误
adb logcat -s AndroidRuntime:E DEBUG:E flutter:E *:S
// ❌ 出问题只会 adb logcat 然后被刷屏淹没 // ✅ 按 tag + 级别 + pid 三层过滤,必要时 adb bugreport 拿完整快照
4. forward / reverse:热重载与开发服务器的命脉
adb forward 把宿主机端口映射进设备,adb reverse 反过来把设备请求转到宿主机。RN 的 Metro(8081)、Flutter 的调试通道都靠它。
1
2
adb reverse tcp:8081 tcp:8081 # 让设备访问宿主机的 Metro/DevServer
adb forward tcp:8081 tcp:8081 # 反向(旧设备/部分场景)
Flutter 热重载失败常因 forward 通道断了(USB 接触不良),表现是 Error connecting to the service protocol。先 adb devices 确认在线,再 kill-server/start-server。
5. dumpsys 与 bugreport:系统级透视
1
2
3
4
5
6
adb shell dumpsys meminfo com.example.app # 内存:Dalvik/Native/Graphics 分项
adb shell dumpsys activity top # 当前栈顶 Activity
adb shell dumpsys battery set level 10 # 模拟低电量(测省电逻辑)
adb shell screencap -p > shot.png # 截屏导到本地
adb shell screenrecord /sdcard/d.mp4 # 录屏(默认 3 分钟)
adb bugreport bug.zip # 抓 ANR/crash/内存的完整快照
Flutter 应用看 Graphics 行(Skia/GPU 显存)、RN 看 Native Heap,是判断内存泄漏的首要指标。
6. ANR 与崩溃抓取
ANR 阈值:输入事件 5s 无响应、前台 BroadcastReceiver 10s、前台 Service 20s 未完成。日志里搜 ANR in;未 root 真机直接 adb bugreport,在解压后的 bugreport-*/FS/data/anr/traces.txt 里看主线程堆栈(谁持锁、卡在哪)。
1
2
adb bugreport bug_$(date +%Y%m%d_%H%M%S).zip
unzip bug.zip && find . -name traces.txt -exec cat {} \;
其实你每天都在用
flutter run装不上:直接adb install build/app/outputs/flutter-apk/app-debug.apk看详细报错- 真机热重载断连:八成是
adb reverse掉了,重连即可 - RN 红屏但 Metro 正常:
adb reverse tcp:8081 tcp:8081没建上 - 线上反馈”偶尔卡死”:
dumpsys meminfo前后对比,看 Native/Graphics 是否只涨不跌 - 想截图给同事看 bug:
adb exec-out screencap -p > bug.png一行搞定 - 复现不了的崩溃:
adb logcat -v time > full.txt一直录,复现后搜FATAL EXCEPTION - 低电量逻辑测不了:
adb shell dumpsys battery set level 5模拟
常见误解(FAQ)
❌ 误区一:”无线调试就是 adb connect IP:5555,连不上就是网络问题”
Android 11+ 改了协议:必须先在「无线调试」里拿到配对码走 adb pair,再 adb connect,老设备的 tcpip 5555 直连方式在新系统上已不适用。连不上先看 adb devices 是 unauthorized 还是 offline。
❌ 误区二:”logcat 级别是 4 个”
其实是 V/D/I/W/E/F 六个(外加 A)。面试被问到别数少。*:E 表示”E 及以上(E/F)”,*:S 表示全部静默——后者常配合 -s tag:V 做精确过滤。
❌ 误区三:”ANR 看 logcat 就行”
logcat 只能看到 ANR 被系统记录的瞬间,真正的主线程堆栈在 /data/anr/traces.txt,普通真机读不了,必须 adb bugreport 打包后从里面取。只盯 logcat 会漏掉”谁持锁卡住主线程”的根因。
❌ 误区四:”有了 Flutter/RN 的日志命令就不用学 ADB”
flutter logs 本质就是封装的 adb logcat。一旦遇到原生层崩溃(Java/Kotlin Exception)、GPU 内存、Activity 栈、ANR,框架命令给不出信息,最终还是得回到 adb shell dumpsys 和 bugreport。
一句话总结
ADB 是 Android 调试的「地基」——USB/无线连接、logcat 过滤、forward/reverse 打通热重载、dumpsys 透视系统、bugreport 兜底疑难,五件套练熟,你就不只是”会敲 flutter run“的人,而是能在真机现场独立破案的那一个。