8、日志分析(Logcat):adb logcat 基础用法、日志级别(V/D/I/W/E)、过滤日志、保存日志到文件
做 Android 开发,说白了就是跟 Bug 打交道。而 Logcat,就是我们手里最趁手的「探针」。我见过太多新手,遇到问题就两眼一抹黑,其实只要学会看日志,大部分问题都能自己搞定。
这一章,我就带你彻底搞懂 Logcat。从最基础的命令,到高级的过滤技巧,再到实战中的避坑指南,咱们一步到位。
8.1 什么是 Logcat?
Logcat 是 Android 系统提供的一个日志输出系统。你的 App 里写的 Log.d()、Log.e(),系统底层的各种运行信息,都会通过它吐出来。
你可以把它想象成飞机的「黑匣子」—— 飞机出事了,第一件事就是找黑匣子。App 出问题了,第一件事就是看 Logcat。
adb logcat
就这么简单。在终端里敲下这行命令,日志就会像瀑布一样刷刷地往下滚。
8.2 日志级别(V/D/I/W/E)
日志是有「等级」的。就像新闻一样,有「一般消息」、「重要通知」、「紧急警报」。Android 定义了五个级别,从低到高分别是:
| 级别 | 缩写 | 含义 | 使用场景 |
|---|---|---|---|
| Verbose | V | 啰嗦模式 | 开发调试时随便打,发布版本要删掉 |
| Debug | D | 调试信息 | 排查问题时临时加的日志 |
| Info | I | 普通信息 | 记录关键流程,比如「登录成功」 |
| Warning | W | 警告 | 可能有问题,但还没崩 |
| Error | E | 错误 | 出异常了,赶紧看! |
我个人习惯,开发时用 Log.d() 打调试日志,上线前统一清理。千万别把 Log.v() 留在线上版本里,那日志量能把用户手机撑爆。
在代码里,你可以这样打日志:
Log.d("MainActivity", "用户点击了登录按钮");
Log.e("MainActivity", "登录失败,错误码:" + errorCode);
第一个参数是「标签」(Tag),第二个是「内容」。标签用来区分日志来自哪个类,内容就是你想看的信息。
8.3 过滤日志:只抓你想要的
直接跑 adb logcat,你会看到海量信息。系统日志、其他 App 的日志、内核日志…… 全混在一起。这时候就需要过滤了。
8.3.1 按标签过滤
这是最常用的方式。比如我只想看 MainActivity 的日志:
adb logcat -s MainActivity
或者同时看多个标签:
adb logcat -s MainActivity:V NetworkUtils:D
这里的 :V 和 :D 表示日志级别。意思是「只看 MainActivity 的 Verbose 及以上级别,以及 NetworkUtils 的 Debug 及以上级别」。
8.3.2 按级别过滤
我只想看 Error 级别的日志,其他一概不管:
adb logcat *:E
这个命令的意思是「所有标签(*),只看 Error 及以上级别」。嗯,这里要注意,*:E 会显示所有 App 的 Error 日志,包括系统本身的。如果你只想看自己 App 的,最好结合标签过滤。
8.3.3 用 grep 做高级过滤
有时候标签不够用,我想搜包含「login」关键字的日志:
adb logcat | grep "login"
这是 Linux 的管道操作。把 Logcat 的输出,交给 grep 命令做文本搜索。我在项目中遇到过一个问题:某个接口返回了奇怪的 JSON,我就是用 grep "response" 从海量日志里捞出来的。
我曾经在线上环境用 adb logcat | grep "password" 查问题,结果把用户的密码明文日志给抓出来了。后来被安全团队约谈…… 所以,永远不要在日志里打印敏感信息,比如密码、Token、身份证号。
8.4 保存日志到文件
日志一直滚屏,你根本来不及看。更常见的是把日志保存下来,慢慢分析,或者发给同事帮忙看。
8.4.1 保存到本地文件
adb logcat -d > app_log.txt
-d 参数的意思是「dump(倾倒)」,把当前缓冲区里的日志一次性倒出来,然后退出。这样你得到的是一个静态的文本文件。
如果你想持续记录,可以不加 -d:
adb logcat > app_log.txt
这样日志会一直写入文件,直到你按 Ctrl + C 停止。
8.4.2 带时间戳保存
分析问题时,时间戳非常关键。比如用户说「我点了按钮后 3 秒才响应」,你就能精确看到那 3 秒里发生了什么。
adb logcat -v time > app_log_with_time.txt
-v time 表示输出格式带时间。还有其他格式,比如 -v threadtime 会显示线程 ID 和时间,适合分析多线程问题。
8.4.3 清空缓冲区再保存
有时候日志太旧了,我想从「现在」开始抓:
adb logcat -c
adb logcat > fresh_log.txt
-c 是 clear(清空)的意思。先清空缓冲区,再开始抓取,这样文件里就只有新日志了。
我一般会这样组合使用:
adb logcat -c && adb logcat -v time -s MyApp:V > myapp_$(date +%Y%m%d_%H%M%S).log
这条命令做了三件事:清空旧日志、只抓 MyApp 标签的日志、带时间戳、文件名带当前时间。这样每次抓的日志都不会覆盖,而且一目了然。
8.5 知识体系总览
下面这张图,帮你把 Logcat 的核心知识点串起来:
8.6 实战:一次完整的日志分析流程
光说不练假把式。我给你模拟一个真实场景:
用户反馈,点击「登录」按钮后,App 闪退了。你该怎么查?
- 先清空旧日志:
adb logcat -c - 复现问题:让用户再点一次登录按钮
- 抓取日志:
adb logcat -v time -d > crash_log.txt - 分析日志:打开文件,搜索
FATAL EXCEPTION或AndroidRuntime
为什么会搜这两个关键词?因为 App 崩溃时,Android 系统会打印一条 FATAL EXCEPTION 日志,后面跟着完整的堆栈信息。你只要找到它,就能定位到是哪行代码出了问题。
我记得有一次,一个同事搞了三天没找到的 Bug,我过去一看日志,发现是 NullPointerException,空指针。原因很简单:登录接口返回的数据里,有个字段是 null,但代码直接调用了它的方法。这种问题,看日志五分钟就能定位。
Logcat 是 Android 调试的「眼睛」。学会用它,你就从「盲人摸象」变成了「明察秋毫」。别怕日志多,学会过滤和保存,你就能从海量信息里快速找到关键线索。