还在用 BuildConfig.DEBUG 控制 Log 开关?你需要试试这个!

3,185 阅读2分钟
原文链接: github.com

利用Proguard移除无用代码以及碰到的坑

0x00 起因

今天用反编译工具反编译了下App,如图:

截图 可以看到,里面用来打印生命周期的代买还在里面,虽然说我们一般会封装成log的工具类,然后利用BuildConfig.DEBUG来判断是否打印日志,但是这种也太low了是吧?毕竟对于有洁癖的人来说还是多了个空方法,看着不爽。

0x01 解决过程

由于之前没看到过相关资料,因此只能搜索,历经切换了多次关键字后终于发现了Proguard中-assumenosideeffects这个参数,通过配置可以在release中移除某些代码。

具体配置是:

  • 必须是Release模式并且minifyEnabled置为true,这样才会使用Proguard混淆

  • 在本Module的混淆配置文件proguard-rules.pro中增加下面的代码:

      -assumenosideeffects class android.util.Log {     
      public static *** d(...);     
      public static *** e(...);     
      public static *** i(...);     
      public static *** v(...);     
      public static *** println(...);     
      public static *** w(...);     
      public static *** wtf(...);
      }
    
  • 确保混淆配置文件中没有关闭压缩,也就是说不要有-dontoptimize这个配置

你以为到这里就结束了?呵呵,TYTN! 我按照这个打包了好多次,就是没有效果,三个关键点比对了好多次,就是没效果。后来,终于找到了原因,原来buildTypes中的release中是这样写的:

release {
        minifyEnabled true
        zipAlignEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
}

注意,问题就出在getDefaultProguardFile('proguard-android.txt')这里,这里的proguard-android.txt指向的是SDKsdk_dir/tools/proguard/proguard-android.txt,这里面有一句: 截图

问题就在这里,去掉这里或者直接在buildTypes移除缺省的配置(前提是保证自定义的配置是完整的满足混淆的)即可。

0x02 最后

关于-assumenosideeffects这个参数如何能移除代码、能移除哪些类型的可参考下面的第一篇资料。 最后奉上处理后的代码: 截图 是不是干净多了?

0x03 补充

上面最终结果的图中,圈出来了两个地方:

  • 第一个,由于开启代码优化,因此Proguard就把代码中的一个静态方法直接内联到调用的地方了(类似C++的内联函数)
  • 有些log里面的变量是没法去掉的,因此会多一个无用的字符串,具体参考第一个参考资料。

祝大家愉快!!!

0x04 参考资料

0x05 关于

Author peerless2012

Email peerless2012@126.con

Blog peerless2012.github.io