在项目开发过程中,为了调试经常会打印log。有的童鞋喜欢用System.out.println()或者System.err.println()。更多的童鞋会选择用android.util.Log的方法。
选用android.util.Log无疑是明智的。
在Android的Code Style Guidelines文档中,明确的指出:System.out.println()
(or printf()
for native code) should never be used详见(Code Style Guidelines),原因是:
System.out and System.err get redirected to /dev/null, so your print statements will have no visible effects. However, all the string building that happens for these calls still gets executed
• android.util.Log 可以定义自己的TAG,sys.out 不能。
• android.util.Log可以多个等级(VERBOSE, DEBUG, INFORMATION,WARNING,ERROR),sys.out 不能。
使用println()打印的日志也是显示在logcat中(我刚从java学Android,打印第一个log用的是println(),在console中怎么也找不到日志,差点放弃,真是o(╯□╰)o )。System.out.println("Hello!") 相当于Log.i("System.out","Hello!")。
我参加工作接手的第一个项目是从兼职外包手里拿过来的代码,项目里Utils包中有个Logger类,专门控制打Log,当时我是不太理解的,直接用android.util.Log不是也是一行代码就可以调试的嘛(⊙_⊙)?然后发现他的Logger类中有个标记boolean debug,if(debug)才会打印log。我就自以为明白了,可以全局控制呀!正式发包的时候把debug = false,就没有多余的log日志了!其实当时我并没明白多余的log日志有什么坏处。
关键问题来了,log日志到底会暴露什么?这个简单的boolean标记能真正的隐藏关键信息么?
说个容易理解的。
有个联网获取用户信息并显示的功能,在程序调试过程中,没有达到预期的效果,(按我的逻辑)首先,我会打印出调用接口的URL,看是否正确,然后,打印出服务器返回的数据,看数据是否正常,再然后,打印展示信息,看展示过程是否异常。
经过调试修改,该功能完成,喜悦之余,忘记删除log;或者为了方便调试就没想过要删除log。
我见过不少代码这样打log的:
Log.i("url","http://*******");
Log.i("获取用户信息成功",respons);
直接连接手机在Logcat中看,接口直接暴露出来,不用反编译APK,还把每个接口是什么功能都告诉了别人。
这些信息很容易就被人利用。
那么,通过标识来关闭log的方法是否靠谱呢?
从某种程度上说,通过标识来关闭log的方法,只是增加了获取log信息的难度,增加了一丢丢难度而已。
因为有反编译,因为有逆向镜像。
那些有不良企图的人轻易能反编译你的APK,把标识改成true,重新打包,log信息立马全现。
那到底怎么办呢,总不能从头检查代码,把log相关代码都手动删除了吧,工作量不说,调试程序很不方便的说。
so,终于说到重点了。
最靠谱的方法 :配置Proguard。此处默认读者懂的代码混淆。。
在配置文件中增加如下:
-assumenosideeffects class android.util.Log {
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
记得 在project.properties添加proguard.config=proguard.cfg
这样,打出的APK包就不会包含log的代码了。