在日常的Android开发中,日志打印是一项必不可少的操作,我们通过分析打印的日志可以分析程序的运行数据和情况。然而使用日志打印的正确姿势又是怎样呢,如何屏蔽日志信息输出呢,本文将逐一进行回答。
哪些形式
System.out.println
这是标准的Java输出方法,相信很多公司都不提倡使用,这里进行列举,目的是为了提醒大家不用。
Android Log
Android自身提供了一个日志工具类,那就是android.util.Log。使用很简单,如下
1
|
|
TAG选取
选用人名
关于TAG的选取,很多人都曾采用人名的形式,比如
1
|
|
这样做的目标一是为了过滤方便,当一个人在写一个模块多个文件时,使用这个形式,过滤起来很容易帮助理解程序的执行情况。另外的目的就是为了表明日志周围代码的作者姓甚名谁。
然而,我却不推荐这种人名作为TAG的形式。原因如下
- 以人名作为关键字过滤,不易确定产生日志的类文件
- 随着某个人模块实现的增加,过滤人名易产生来自其他模块的干扰信息。
动态选取
还有一种选取LOGTAG的方式,就是
1
|
|
这样使用,得到的LOGTAG的值就是DroidSettings,然而并非如此,当DroidSettings这个类进行了混淆之后,类名变成了类似a,b,c这样的名称,LOGTAG则不再是DroidSettings这个值了。这样可能造成的问题就是,内部混淆有日志的包,我们去过滤DroidSettings 却永远得不到任何信息。
推荐的记录形式
推荐的形式就是以字符串字面量形式去设置LOGTAG。如下,在DroidSettings类中
1
|
|
优雅打印日志的姿势
什么才是打印日志的优雅姿势是,我认为一条好的日志需要包含以下三点
- 这条日志所在的类,我们通过LOGTAG可以表示
- 这条日志所在的方法,需要加入方法名的字符串
- 必要的其他信息,比如参数或者局部变量。
结合三点,下面是一个符合规则的简单示例
1 2 3 4 5 |
|
上面的代码,包含了所在类(LOGTAG),方法名(getBookName), 参数(bookId),局部变量(bookName)。必要的信息都展示了出来,对于了解程序运行很有帮助。
屏蔽日志输出
在Android中进行屏蔽日志,有两种实现形式,一种是在编译期屏蔽,另一种则是从运行时进行屏蔽,后者相对比较常见,从后向前介绍。
运行时屏蔽
在运行时屏蔽日志,通常的做法是创建一个自定义的类,比如叫做DroidLog
1 2 3 4 5 6 7 8 9 10 |
|
在编码时,我们调用DroidLog.i方法来记录日志,然后在打包时,修改ENABLE_LOG的值为false,这样就能屏蔽了日志输出。
然后运行时屏蔽的方案实际上有一点小问题,比如
1 2 3 |
|
虽然上面的日志不会打印,但是"sdkVersion=" + Build.VERSION.SDK_INT + "; Locale=" + Locale.getDefault()
这段字符串拼接语句却实实在在执行了。总的来说,还是会产生一些影响。
关于字符串拼接的细节,可以阅读Java细节:字符串的拼接
编译期屏蔽
既然运行时屏蔽存在问题,那么是否可以提前到编译期进行屏蔽呢,答案是肯定的。这里我们就使用了Proguard的一个小功能。
assumenosideeffects从英文单词上去理解,意思为 假设没有副作用。该功能属于优化的一种方式,该功能常常用来处理日志打印,比如我们想要屏蔽掉来自DroidLog的日志打印。 在混淆的配置文件中,加入下列代码
1 2 3 |
|
然而仅仅处理DroidLog是不够的,因为我们无法保证团队其他成员是否使用了原生的android.utils.Log来进行日志打印(尽管有编码约束)
1 2 3 4 5 6 7 8 9 |
|
一般写到这里,基本可以结束,但是我们还需要探究一下,编译期屏蔽是否和运行时屏蔽一样有着同样的问题呢? 我们接下来证明
首先,我们选用这段代码作为例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
然后修改混淆文件proguard-project.txt,启用混淆处理。
1 2 3 4 5 6 7 8 9 |
|
然后使用Eclipse的导出功能,生成指定签名的APK包,运行必然没有日志输出。
接下来对生成的APK包进行反编译,得到的smali文件。查看MainActivity.smali。
注意:Proguard进行优化,发生了内联操作,讲dumpDebugInfo的方法体实现提取到onCreate方法中。
onCreate方法体中没有任何关于DroidLog.i
方法的调用,但是"sdkVersion=" + Build.VERSION.SDK_INT + "; Locale=" + defaultLocale
对应的字符串拼接操作依然存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
因此,无论是运行时日志屏蔽还是编译期,message参数上发生的字符串拼接都依然存在。但是编译期屏蔽减少了方法调用(即方法进出栈操作),理论上编译期屏蔽日志更优。
相关推荐
android自定义log日志输出工具,该工具类具有以下优点: 1 在LogUtlis方法的第一个参数中填this可以输出当前类的名称,特别是在匿名内部类使用也可以输出当前类名。 如 : LogUtils.i(this,”这是一个实用的日志...
android.util.Log is the most usable library of the Android. But, when the app released on the market, some important information is clearly forgotten by the developer. All logs are disabled by Debug...
一个类实现更实用的 Android Log 工具 —— 1 个类,100 个方法、9 KiB
Log4a is an mmap based, high-performance, highly available Android log collection framework | Log4a 是一个基于 mmap, 高性能、高可用的 Android 日志收集框架
android log 查看工具,告别 adb logcat ,对log分析henyou希望能帮助到大家,谢谢!!!
Android显示Log信息(带行号),非常好用的Android工具类!
自定义android Log类,请参看我的blog
android 下方便的打印log 在sd上写入log
Android log4j使用DemoAndroid log4j使用DemoAndroid log4j使用DemoAndroid log4j使用Demo
888个log android log
在Android群里,经常会有人问我,Android Log是怎么用的,今天我就把从网上以及SDK里东拼西凑过来,让大家先一睹为快,希望对大家入门Android Log有一定的帮助.
兼容 Android Studio 3.1.0 的 Logcat 完美显示日志 兼容 Kotlin 可设置 Log 开启和关闭 可设置是否输出到控制台(Logcat) 可设置 Log 全局 Tag 全局 Tag 为空时 Tag 为当前类名 可设置 Log 是否显示头部信息 Log ...
Android 使用log4j所需要的jar包
当Android代码java层发生崩溃的时候,会将崩溃信息收集起来
Graylog client for Android devices Graylog is a rsyslog web interface based on Ruby On Rails: http://github.com/lennartkoopmann/Graylog Watch your favorite errors now mobile on your android device! :)...
有需要可以看看,动态将想要的数据通过该接口直接写到本地文件
Android Log系统介绍 (基于Android N). 从调用 Log.d("xxx", "test") 到你从logcat中看到它的输出, 这中间都发生了什么? native代码中的"ALOG/ALOGD/ALOGE"等的"宏函数"log都打到哪里去了? 什么是 kernel log? 请看...
一个收集 app 输出日志的工具,输出文件:模拟器是 /sdcard/Android/data/项目包名/cache/,真机是 /Android/data/项目包名/cache/,里面的 crash 目录是崩溃日志,log 目录是 logcat 日志。 如何使用 在 module ...
Log4Android2PCv2.3.7