在应用开发中, 我们常常会进行日志打印或者 debug 调试, 以此来分析运行时的一些信息, 便于发现 bug 和问题. Android Studio 的 Debug 功能很好用, 但是有时候有些情况下, 就显得不是那么快捷和便利.
比如
我们调试的点在应用一打开的时候, 很靠前, 例如 Application 的 onCreate 方法中, 以至于我们不能足够快的设置进程为 debug 模式
虽然上面的情况可以通过 Android Studio 的 debug 运行来解决, 但是如果项目很大的话, 运行起来也会比较耽误时间
那么怎么解决上面的问题呢, 其实只需要执行一行命令即可
adb shell am set-debug-App -w com.example.jimmy.appdebugsample
其中
set-debug-App 用来应用为 debug 模式
-w 意思为 wait, 在进程启动的时候, 等待 debugger 进行连接
com.example.jimmy.appdebugsample
代表想要调试的应用的包名或 ApplicationId
执行上面的命令, 当我们再次启动目标应用时, 会得到这样的画面
然后, 我们就会有足够的时间, 来使用 Run-> Attach Debugger to Android Process 来绑定进程 debug. 绑定后对话框消失, 下次启动就是正常的启动(没有上面的对话框了)
那么一次 debug 不一定能解决问题, 多次调试则在所难免, 那么每次都要执行这个命令么?
答案是可以, 但是有更好的方式. 即
adb shell am set-debug-App -w --persistent com.example.jishuxiaoheiwu.appdebugsample
上面的代码和之前有所不同, 表现在一个 --persistent
-persitent 意思是持久的, 意思是一直设置这个应用为调试模式, 即每次开启 (进程创建) 都会弹出对话框, 即使卸载再安装或者更新应用
多次 debug 完成后, 想要恢复正常的启动:
adb shell am clear-debug-App
二, Android 调试工具 addr2line 使用:
1. 将 ndk 中的 ARM-Linux-androideabi-addr2line 可执行文件的路径加入配置文件~/.bashrc 中, 例如:
export PATH=$PATH:~/dlna/Android-ndk-r6b/toolchains/ARM-Linux-androideabi-4.4.3/prebuilt/Linux-x86/bin
2. 使配置生效:
source ~/.bashrc
3. 使用工具. 例如:
ARM-Linux-androideabi-addr2line -C -f -e ~/workspace/DLNA/libs/armeabi/libctrlpt.so 0003deb4
其中, 0003deb4 为堆栈信息中 pc 的值.
使用 addr2line 追踪自有动态库 (so 文件) 的 bug, 补充:
解决出现 ??:0 , 没法展示源代码行数的问题
在 Android.mk 文件中:
Java 代码
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wl,-Map=test.map -g
补充 2 个编译参数 -Wl,-Map=test.map -g .
增加 gcc 警告和调试标志
ARM-Linux-androideabi-addr2line -C -f -e / 项目目录 / obj/local/armeabi/libfaa_jni.so 0024362e
tip: 1, 注意调试文件的位置在 obj 目录下, 并非 libs 目录下生成的 so 文件
2,0024362e 为出错的机制位置
还有:
在 jni / 目录下增加 Application.mk 文件, 修改为 debug 模式, 进行调试 APP_OPTIM := debug
----- 凡是 backtrace 下带 pc 字样的地址都可以用 NDK 中或 Linux 下的 ARM-Linux-androideabi-addr2line 工具将地址映射成函数名字.---- 定位到具体位置
三, 使用 GDB
GNU 项目调试程序 (GDB) 是常用的 Unix 调试程序. 本页详细介绍了如何使用 gdb 调试 Android 应用和进程(面向平台开发者). 对于第三方应用开发, 请参阅调试您的应用.
调试运行中的应用或进程
要连接到已在运行的应用或本机守护进程, 请配合使用 gdbclient 和 PID. 例如, 要调试 PID 为 1234 的进程, 请运行:
gdbclient 1234
此脚本会设置端口转发, 在设备上启动相应的 gdbserver, 在主机上启动相应的 gdb, 配置 gdb 以找出符号, 然后将 gdb 连接到远程 gdbserver.
调试本机进程启动
要在进程启动时对其进行调试, 请使用 gdbserver 或 gdbserver64(适用于 64 位进程). 例如:
adb shell gdbserver :5039 /system/bin/MY_TEST_APP
输出示例:
- Process MY_TEST_APP created; pid = 3460
- Listening on port 5039
接着, 从 gdbserver 输出内容中找到应用 PID, 并在另一个终端窗口中使用:
gdbclient APP_PID
最后, 在 gdb 提示处输入 continue.
注意: 如果您指定了错误的 gdbserver, 将会收到没任何帮助的错误消息(例如 "Reply contains invalid hex digit 59").
调试应用启动
有时, 您需要在应用启动时对其进行调试; 例如在应用发生崩溃时, 您需要逐步检查代码, 以查看崩溃之前发生的情况. 附加调试程序有时能解决问题, 有时不能解决问题, 因为应用可能会在您可以附加调试程序之前崩溃. logwrapper 方法 (用于 strace 和 valgrind) 不一定能解决所有的问题, 因为应用可能没有权限打开端口, 而 gdbserver 会继承这项限制.
要调试应用启动, 请使用 "设置" 中的开发者选项, 指示应用等待附加 Java 调试程序:
请依次转到 "设置">"开发者选项">"选择调试应用", 并从列表中选择您的应用, 然后按等待调试程序.
启动应用, 您可以从启动器启动, 也可以在命令行中运行以下命令来启动:
am start -a Android.intent.action.MAIN -n APP_NAME/.APP_ACTIVITY
等待应用加载, 然后等待系统显示一个对话框提示您应用正在等待附加调试程序.
正常附加 gdbserver/gdbclient, 设置断点, 然后继续运行该进程.
要让应用实际运行, 请附加 Java 调试网络协议 (JDWP) 调试程序, 例如 Java 调试程序 (jdb):
- adb forward tcp:12345 jdwp:XXX # (Where XXX is the pid of the debugged process.)
- jdb -attach localhost:12345
调试崩溃的应用或进程
如果您希望 debuggerd 暂停崩溃的进程, 以便您可以附加 gdb, 请设置相应的属性:
- //Android 7.0 Nougat and later.
- adb shell setprop debug.debuggerd.wait_for_gdb true
- //Android 6.0 Marshmallow and earlier.
- adb shell setprop debug.db.uid 999999
在寻常崩溃输出的结尾处, debuggerd 会提供有关如何使用以下命令来连接 gdb 的说明:
gdbclient PID
无符号调试
对于 32 位 ARM, 如果您的指令中没有符号, gdb 就不清楚自己正在反汇编哪个指令集(ARM 或 Thumb). 要指定缺少符号信息时选为默认指令集的指令集, 请设置以下属性:
set ARM fallback-mode ARM # or thumb
自己是从事了七年开发的 Android 工程师, 不少人私下问我, 2019 年 Android 进阶该怎么学, 方法有没有?
没错, 年初我花了一个多月的时间整理出来的学习资料, 希望能帮助那些想进阶提升 Android 开发, 却又不知道怎么进阶学习的朋友.[包括高级 UI, 性能优化, 架构师课程, NDK,Kotlin, 混合式开发(ReactNative+Weex),Flutter 等架构技术资料] , 希望能帮助到您面试前的复习且找到一个好的工作, 也节省大家在网上搜索资料的时间来学习.
来源: http://www.jianshu.com/p/a2e93989733f