1. logcat是什么?
logcat是Android开发中常用的一个日志工具.
日志对于一个项目来说是非常重要一环,是可以作为一个功能模块来定义的. 比如:详细的日志信息,可以帮助开发人员快速的分析和定位问题.
那么对于日志工具的使用必须要熟悉,日志的使用技巧也要熟悉.
2. logcat有什么用?
通过对日志内容的过滤帮助研发分析和定位问题.
3. 如何生成日志?
我的日志格式习惯:
public void function(){
Log.d("Class Name","function() ------>");
//TODO: your code at here!
Log.d("Class Name","function() <------");
}
从6个”-“,>和<这三个特征就可以直观的看书当前类执行了哪些函数,以及每个函数消耗的时间(在Android studio).
比如:直接在Android studio的过滤条件中连敲6个’-‘就直观的看出当前代码执行了哪些方法.
但是有时候代码是大家写的,有的同事可能有自己的偏好比如他的风格是这样:
public void function(){
Log.d("Class Name","function() >>>");
//TODO: your code at here!
Log.d("Class Name","function() <<<");
}
每个人习惯不同,谁都不能说服谁. 但是有时候维护的时候自己,那么这个时候就要考验自己的logcat能力.直接把日志导出到my.log文件慢慢看吧.
4. 如何使用logcat输出和过滤日志?
官方用法说明
adb logcat -h //没有这个命令, 系统会给出一个命令列表.
logcat: invalid option -- h
Unrecognized Option
Usage: logcat [options] [filterspecs]
options include:
-s Set default filter to silent.
Like specifying filterspec '*:s'
-f <filename> Log to file. Default to stdout
-r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f
-n <count> Sets max number of rotated logs to <count>, default 4
-v <format> Sets the log print format, where <format> is one of:
brief process tag thread raw time threadtime long
-c clear (flush) the entire log and exit
-d dump the log and then exit (don't block)
-t <count> print only the most recent <count> lines (implies -d)
-t '<time>' print most recent lines since specified time (implies -d)
-T <count> print only the most recent <count> lines (does not imply -d)
-T '<time>' print most recent lines since specified time (not imply -d)
count is pure numerical, time is 'MM-DD hh:mm:ss.mmm'
-g get the size of the log's ring buffer and exit
-b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',
'events', 'crash' or 'all'. Multiple -b parameters are
allowed and results are interleaved. The default is
-b main -b system -b crash.
-B output the log in binary.
-S output statistics.
-G <size> set size of log ring buffer, may suffix with K or M.
-p print prune white and ~black list. Service is specified as
UID, UID/PID or /PID. Weighed for quicker pruning if prefix
with ~, otherwise weighed for longevity if unadorned. All
other pruning activity is oldest first. Special case ~!
represents an automatic quicker pruning for the noisiest
UID as determined by the current statistics.
-P '<list> ...' set prune white and ~black list, using same format as
printed above. Must be quoted.
filterspecs are a series of
<tag>[:priority]
where <tag> is a log component tag (or * for all) and priority is:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal
S Silent (supress all output)
'*' means '*:d' and <tag> by itself means <tag>:v
If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
If no filterspec is found, filter defaults to '*:I'
If not specified with -v, format is set from ANDROID_PRINTF_LOG
or defaults to "brief"
- 操作命令
-s从使用说明上看就是根据TAG来过滤的,比如: “W/ContextImpl”, W就是日志的级别,”ContextImpl”就是TAG.
adb logcat -s "ContextImpl"
-v 格式化,brief process tag thread raw time threadtime long
adb logcat -v brief
adb logcat -v process
-t 打印最近的行
adb logcat -t 10 //最近10行
-t ‘MM-DD hh:mm:ss.mmm’
试过没成功,平时也需要这么用,没有研究。
grep过滤用法
- 按照日志级别过滤
adb logcat | grep "^E"
- 过滤字符串
adb logcat | grep "-"
过滤包名
- 单个应用日志
adb logcat | grep "^..[com.jingdong.app.mall]"
- 多个应用日志
adb logcat | grep "^..[anti] \|^..[dalvik]"
adb logcat | grep "^..anti\|^..dalvik"
- 正则过滤
过滤出来包含”-“号并且是DEBUG级别的日志.
adb logcat | grep "^D.*-"
- 忽略大小写
adb logcat | grep -i "^D.*-"
我的过滤
1. 在命令行下直接使用logcat
db logcat | grep "^.*HttpTaskRunner\|^.*-----\|^.*>>>\|^.*<<<"
db logcat | grep "^.*-----\|^.*>>>\|^.*<<<"
过滤并重定向到文件
db logcat | grep "^.*-----\|^.*>>>\|^.*<<<" >D:\my.log
2. Android Studio中Android Monitor过滤
日志过滤文本框中是支持正则表达式的
|>>>|<<<|------
5. 扩展说明
最广泛的使用场景大致有两个:
1.实现一个全局的日志工具类,通过变量设置支持输出日志到文件或者打印到控制台,便于随意查看和分析. 生产环境中甚至把一些非隐私性的日志输出的用户存储中,在合适的场景下把日志文件回传到服务器.
2.收到用户的反馈信息后,给用户提供一个携带日志的版本,通过这个特殊版本收集用户的app信息,然后分析定位用户的问题.
PS: 最好不要在生产环境使用第一种方式输出日志,很容易泄漏应用的信息,尽管我们可以在打包的时候把日志开关关掉,但是apk是可以解包,修改smali然后重新打包,这样会方便恶意分析人员从日志获取到有用信息.
比较安全的日志输出方法:
1.修改build.gradle
build.gradle中添加如下部分:
android {
buildTypes {
release {
buildConfigField "boolean", "APP_DEBUG", "true"
buildConfigField "String", "PLUGIN_VERSION", '"2.2.0"'
}
debug {
buildConfigField "boolean", "APP_DEBUG", "true"
buildConfigField "String", "PLUGIN_VERSION", '"2.2.0"'
}
}
}
2. 查看修改后的效果(需要编译)
然后查看app\build\generated\source\buildConfig\release\packagename\BuildConfig.java or app\build\generated\source\buildConfig\debug\packagename\BuildConfig.java
多了一个变量:
// Fields from build type: release
public static final boolean DD_DEBUG = true;
3. 代码中使用
if (BuildConfig.DD_DEBUG) {
Log.d(TAG, "mothod() ------>");
}
//TODO: ....
if (BuildConfig.DD_DEBUG) {
Log.d(TAG, "mothod() <------");
}
4. 为什么多写了那么几行?
把自己的代码反编译后对比一下: build.gradle
中 DD_DEBUG
分别设为false和true后的代码.