前言:
俗话说,工欲善其事,必先利其器。logcat是我们通过日志排查bug的重要武器之一。从某个版本开始,logcat改版了,改版之后,也许某些人觉得不太习惯,但是如果稍微学习下之后,就发现新版的logcat真的比老版本的好多太多。
也许某个人懒,不太愿意去android的官网查看官方介绍,那么本地特别适合你,本文就是对官网介绍的详细说明以及实例的演示。
android官网logcat的相关介绍。
https://developer.android.google.cn/studio/debug/logcat?hl=zh-cn
logcat界面基本介绍
首先介绍下logcat界面上的组成:
1.顶部框
名称 | 说明 |
TAB栏 | 一个TAB栏对应一个logcat显示框,可以配置多个 |
设备 | 当同时连接太多设备时,可以选择不同的设备显示其logcat |
筛选框 | 对输出的logcat按照规则进行筛选,具体筛选的规则第二章来讲 |
配置按钮 | 对logcat显示的区域,位置,大小等等进行配置 |
2.左侧栏
名称 | 说明 |
暂停 | 暂停logcat的日志输出,使其保持在当前状态。 这个功能很适合我们排查bug时发现了一场日志,避免后面的持续输出的日志的影响。 |
重启 | 重启logcat功能。 |
置底按钮 | logc不断输出,使显示的log内容一直是最新的,也就是现实log内容的最底部。 |
往上查找 | 往上查找最近一次的堆栈日志。 |
往下查找 | 往下查找最近一次的堆栈日志。 |
分行显示 | 有时候一个logcat内容输出太多,默认一行展示不下就缩略了。选择多行显示时,会分成多行显示。 |
配置显示内容 | 对内容框中显示的内容进行配置 |
分成多块显示 | 底部框分成两块,分别独立显示logcat |
截屏 | 截屏功能 |
录屏 | 录屏功能 |
3.搜索栏
名称 | 说明 |
搜索内容 | 输入搜索的内容,这里支持区分大小写,单词匹配,转义。 |
向上 | 向上查找 |
向下 | 向下查找 |
搜索范围选择 | 选择搜索的范围,比如所有类型,评论中,字符串中等等 |
4.内容框
名称 | 说明 |
时间 | 日志输出的时间,这里的时间为手机上的时间。 |
进程ID和线程ID | 进程ID和线程ID,这里的线程ID指的是在linux虚拟机中的线程ID。 |
TAG | 我们日志中的tag。 |
进程名 | 进程名,如果是APP应用的话一般为包名。 |
日志优先级 | 共有六种登记,分别为verbose/debug/info/warn/error/assert |
日志内容 | 我们日志中的msg。 |
筛选功能
1.包名
我们可以根据包名来对log的内容进行筛选,如果我们筛选的包名是com.xt.appplugin ,则可以在筛选框输入:package:com.xt.appplugin,这样筛选出来的log就只是com.xt.appplugin这个应用输出的了。
如果当前调试的应用就是com.xt.appplugin的话,我们也可以输入:package:mine,mine代表就是当前应用,如下:
2.进程名
进程名和包名有什么区别呢?因为一个应用可以多进程,如果我们只关心其中某一个进程的日志输出,就可以使用这个功能。
为了方便读者理解,我们举例说明一下,测试代码如下:
//Activity中
findViewById(R.id.text1).setOnClickListener(v -> {
Log.i("lxltest", "button1 press");
Intent intent = new Intent(this, TestService.class);
startService(intent);
});
//Service中
public class TestService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.i("lxltest", this.getClass().getSimpleName() + ",onCreate");
}
}
如果我们输入的筛选内容是:package:com.xt.appplugin
则输出日志内容为:
2023-03-16 10:46:07.059 9333-9333 lxltest com.xt.appplugin I button1 press
---------------------------- PROCESS STARTED (9381) for package com.xt.appplugin ----------------------------
2023-03-16 10:46:07.215 9381-9381 ziparchive com.xt.appplugin W Unable to open '/data/data/com.xt.appplugin/code_cache/.overlay/base.apk/classes3.dm': No such file or directory
2023-03-16 10:46:07.216 9381-9381 .appplugin:aaaa com.xt.appplugin W ClassLoaderContext classpath size mismatch. expected=0, found=1 (PCL[] | PCL[/data/data/com.xt.appplugin/code_cache/.overlay/base.apk/classes3.dex*1426120062])
2023-03-16 10:46:07.230 9381-9381 GraphicsEnvironment com.xt.appplugin V ANGLE Developer option for 'com.xt.appplugin' set to: 'default'
2023-03-16 10:46:07.230 9381-9381 GraphicsEnvironment com.xt.appplugin V ANGLE GameManagerService for com.xt.appplugin: false
2023-03-16 10:46:07.231 9381-9381 GraphicsEnvironment com.xt.appplugin V Updatable production driver is not supported on the device.
2023-03-16 10:46:07.236 9381-9381 NetworkSecurityConfig com.xt.appplugin D No Network Security Config specified, using platform default
2023-03-16 10:46:07.236 9381-9381 NetworkSecurityConfig com.xt.appplugin D No Network Security Config specified, using platform default
2023-03-16 10:46:07.239 9381-9381 lxltest com.xt.appplugin
而我们输入的筛选内容如果是:process:com.xt.appplugin:aaaa
则输出内容是:
---------------------------- PROCESS STARTED (9591) for package com.xt.appplugin ----------------------------
2023-03-16 10:47:08.735 9591-9591 ziparchive com.xt.appplugin W Unable to open '/data/data/com.xt.appplugin/code_cache/.overlay/base.apk/classes3.dm': No such file or directory
2023-03-16 10:47:08.737 9591-9591 .appplugin:aaaa com.xt.appplugin W ClassLoaderContext classpath size mismatch. expected=0, found=1 (PCL[] | PCL[/data/data/com.xt.appplugin/code_cache/.overlay/base.apk/classes3.dex*1426120062])
2023-03-16 10:47:08.750 9591-9591 GraphicsEnvironment com.xt.appplugin V ANGLE Developer option for 'com.xt.appplugin' set to: 'default'
2023-03-16 10:47:08.751 9591-9591 GraphicsEnvironment com.xt.appplugin V ANGLE GameManagerService for com.xt.appplugin: false
2023-03-16 10:47:08.751 9591-9591 GraphicsEnvironment com.xt.appplugin V Updatable production driver is not supported on the device.
2023-03-16 10:47:08.756 9591-9591 NetworkSecurityConfig com.xt.appplugin D No Network Security Config specified, using platform default
2023-03-16 10:47:08.757 9591-9591 NetworkSecurityConfig com.xt.appplugin D No Network Security Config specified, using platform default
2023-03-16 10:47:08.760 9591-9591 lxltest com.xt.appplugin I TestService,onCreate
2023-03-16 10:47:13.687 9591-9602 System com.xt.appplugin W A resource failed to call close.
区别其实就是少了主进程的下面这条日志:
2023-03-16 10:46:07.059 9333-9333 lxltest com.xt.appplugin I button1 press
3.TAG
TAG就比较容易理解了,根据输入的TAG进行筛选。这里的tag使用的是模糊匹配。
比如下面代码:
Log.i("lxltest", "button press");
Log.e("lxl", "button end");
如果我们使用的是:tag:lxl
则最终的输出内容就是,会把所有tag以lxl为前缀的日志全部筛选出来。
2023-03-16 10:49:53.200 9535-9535 lxltest com.xt.appplugin I button press
2023-03-16 10:49:53.200 9535-9535 lxl com.xt.appplugin
而如果使用lxltest,则只会筛选出button press这一条了。
4.日志级别
日志级别使用的关键词是level,从低到高分别是:verbose/debug/info/warn/error/assert六种级别。
筛选低级别的日志可以打印高级别的日志,反之则不行。
我们仍然用代码来验证下:
Log.v("lxltest", "level verbose");
Log.d("lxltest", "level debug");
Log.i("lxltest", "level info");
Log.w("lxltest", "level warn");
Log.e("lxltest", "level error");
//打印assert级别的日志
Log.println(Log.ASSERT, "lxltest", "level assert");
如果筛选框输入的是:level:verbose,则日志内容输入如下:
如果筛选框输入的是:level:info,则日志内容输入如下:
如果筛选框输入的是:level:assert,则日志内容输入如下:
5.内容
默认输出全部日志如下:
内容筛选支持模糊搜索,筛选框输入:message:level,因为level对所有的字符串都生效,所以日志全部输出,显示如下:
筛选框输入message:level info,因为只能匹配level info这一项,所以显示内容如下:
内容筛选时,输入也可以输入message:'level info'和也可以输入message:level info的效果是一样的。
6.时间
关键词age,我们可以通过这个关键词对日志以时间纬度进行一定的筛选。
比如我想筛选10分钟内的所有日志,则筛选框输入:age:10m即可,其它时间同理,最大支持到天。
单位 | 介绍 |
s | 秒 |
m | 分钟 |
h | 小时 |
d | 天 |
值得注意的是,这里的筛选时间指的是以电脑时间对日志的时间进行筛选。举例例子,电脑时间为12:30,手机时间为12:00。筛选10m内所有日志,AS会去寻找所有时间范围在12:20到12:30之间的日志,这肯定是找不到的,所以最终的日志显示就是空。所以使用这一筛选项时,务必保证手机和电脑时间是同步的。
7.多选-且
大多数情况下,单一的某一个筛选条件肯定是不够的,所以就需要多个筛选条件组合起来用。
logcat筛选框中,如果同时输入多个条件,默认情况下不同类型的筛选,是且的关系。
比如如下的日志:
Log.v("lxltest", "level verbose");
Log.d("lxltest", "level debug");
Log.i("lxltest", "xxxxx info");
Log.w("lxltest", "level warn");
Log.e("lxltest", "level error");
Log.println(Log.ASSERT, "lxltest", "level assert");
筛选条件输入两个:message:level level:warn
这时候level verbose的这条日志就会被过滤掉,只显示其余的3条日志,xxxxx info
如果是相同类型的筛选,则默认是或的关系,比如还是上面的那个例子,
我们输入筛选条件:message:level message:info
因为上面六个选项中,使用模糊匹配,全部满足,所以六条日志全部显示出来了
如果相同类型仍然进行且的筛选,则我们需要改一下筛选条件:message:level & message:warn
这时候同时满足message中包含level和warn的只有level warn这一条,所以也就展示了这一条。
8.多选-或
刚才讲过,如果如果同时输入多个不同条件的筛选项,那么是且的关系。如果我们想改成或应该怎么办呢?
还是上面那个例子,我们改一下筛选项:message:level | level:warn
这时候就变成了满足message中包含level或者日志等于大于等于warn的才显示。
9.多选-组合
上面讲了种种筛选的场景,如果仍然无法满足我们的需求怎么办?这时候我们就要使用灵活多样的组合了。
比如来一个实际的场景,我想监控从A应用点击按钮开始,跳转到B应用页面的完整日志流程,其中就包含了多种条件的组合。
1.进程名为com.xt.appplugin(应用A),system_server(系统应用)或com.xt.client(应用B)
2.tag为lxltest或者Activity
3.日志级别为debug
则我们组合上面所列的各种筛选条件,如下:
(process:system_server | process:com.xt.appplugin | process:com.xt.client) & level:debug & (tag:lxltest | tag:Activity)
最终点击按钮(button click),经过系统分发,最终跳转到了应用B。
日志结果如下,我们可以看到跨越三个进程的相关日志。
界面配置
也许有的人会吐槽,新版本的msg太短了,有的吐槽一屏显示的内容太少,别急,通过界面配置,可以打造出我们想要的dream window。
左侧栏功能介绍
首先我们看一下左侧栏有哪些功能
1.日志清空
顾名思义,清空日志内容。
2.日志暂停
我们排查BUG的时候,往往发现问题后还没来得及仔细看,相关的就被后来的日志给挤走了。这时候如果点击了暂停按钮,新的日志就不会继续输出,方面我们排查问题了。
3.logcat重启
顾名思义,重启logcat,如果遇到log不输出等问题可以点击这个按钮。
4.光标置底
选中时,有最新的日志输出时右侧的进度条会自动切换到最底部。
取消选中时,则不会固定在最底部
5.定位上一个/下一个堆栈
当有异常时,点击这个按钮会自动帮我们切换到对应的代码中。
点击下时则帮我们切换到at android.os.Looper.loopOnce(Looper.java:201)这一行所对应的代码。
6.分行显示
不分行显示时:
分行显示时:
7.配置显示内容
目前显示的内容包括时间/进程-线程ID/TAG/进程名/日志级别/MSG内容,是不是觉得太多?如果我只是调试自己的应用,就没必要关心其它进程的日志信息。那么我们就可以进行配置
比如作者删除了进程名和包名,msg可显示的区域一下子就变多了。
8.分屏显示
可以同时显示两块logcat区域,我们可以是上下还是左右的方式显示
9.截屏和录屏
顾名思义,就不过多解释了
顶部框功能集合介绍
顶部功能包括TAB栏,配置按钮
1.TAB栏
tab栏可以配置多个logcat显示框,比如作者就配置了两个logcat框,可以自由切换。
2.配置显示模式
首先我们来讲配置->View Mode,这里可以配置我们期望日志框展示的模式。
比如作者最经常使用的Float模式,一整屏显示日志,超级爽。
3.配置显示区域
接下来讲配置->Move to的功能。这里可以配置日志框显示的区域。
比如改成Left Top