Proguard使用说明

    • 概述
    • 使用
      • proguard配置文件
        • proguard-androidtxt
        • proguard-android-optimizetxt
    • 项目实际应用
      • 常见命令
      • ProGuard文件
      • 还原 ProGuard 混淆过的代码

概述

Proguard 是一个很强悍的工具,它可以帮你在代码编译时对代码进行混淆,优化和压缩。它有一个专门用来减少apk文件大小的功能叫做 tree-shaking。Proguard 会遍历你的所有代码然后找出无用处的代码。所有这些不可达(或者不需要)的代码都会在生成最终的apk文件之前被清除掉。Proguard 也会重命名你的类属性,类和接口,然整个代码尽可能地保持轻量级水平。

Proguard 是一个相当有效地工具。但是能力越大,责任也就越大。但是Proguard它会重度依赖反射。哪些类或者属性需要被处理或者不能处理都要开发者对Proguard 进行配置,对开发者的整体项目把握度有点要求

使用

proguard配置文件

Android本身已经提供了两份关于proguard的配置文件,放在sdk/tools/proguard目录下面,如下:

我们可以在此基础上完成我们所需的混淆功能,当然我们也可以完全自己创建一个配置文件,具体的配置命令参见proguard官网

proguard-android.txt

我们发现Android提供了两个文件,一个是proguard-android-optimize.txt,另一个是proguard-android.txt。
两者最主要的区别是前者加入了一些优化命令。接下来,我们首先分析proguard-android.txt(去掉了一些注释)

-dontusemixedcaseclassnames  #不使用大小写混合,防止解压时在一些不区分大小写系统中出问题
-dontskipnonpubliclibraryclasses #不混淆非公开库文件
-verbose  #混淆时记录日志
-dontoptimize  #不优化输入的类文件  默认情况下,优化标识被关闭。Dex并不喜欢代码通过混淆的优化和预校验步骤运行(它会自己完成这些优化)
-dontpreverify  #不预校验 
-keepattributes *Annotation*  #不混淆注释annotation
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {    #保持native方法不被混淆
    native ;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {  # 保持枚举 enum 类不被混淆
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {  # 保持 Parcelable 不被混淆
  public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class **.R$* {
    public static ;
}

#proguard默认 会检查每一个引用是否正确,但是第三方库里面往往有些不会用到的类,没有正确引用。如果不配置的话,系统就会报错。但如果我们知道这些问题,并确保不引用是安全就可以忽略
-dontwarn android.support.**

proguard-android-optimize.txt

接着我们分析一下proguard-android-optimize.txt,相比proguard-android.txt,主要是加入了一些优化命令,但加入这些优化命令是有风险的,因为在不同版本的Dalvik,并不是所有的优化命令都生效。所以,要是使用这些优化命令,必须确保通过彻底的测试。

-optimizationpasses 5   #表示proguard对你的代码进行迭代优化的次数,迭代会在最后一次无法优化的时候停止
-allowaccessmodification ##优化时允许访问并修改有修饰符的类和类的成员  

更多地优化命令可以查看OptimizationOptions

项目实际应用

常见命令

对于一般应用,使用Android提供的默认混淆文件就够用了。但正常来说,我们还得在其基础上添加一些我们项目实际需要的命令。

  • 对于引入的一些第三方jar不混淆

    如shareSDK:

    -keep class cn.sharesdk.**{*;}
  • 保持泛型,防止类型转换异常

     -keepattributes Signature
  • 反射类不能进行混淆编译

    -keep class (涉及到反射的类).** {*;}
  • 使用一些依赖序列化的库。如fastjson,不能混淆对应的序列化对象,并且必须实现Serializable接口
-keepclassmembers class * implements java.io.Serializable {  
    static final long serialVersionUID;  
    private static final java.io.ObjectStreamField[] serialPersistentFields;  
    private void writeObject(java.io.ObjectOutputStream);  
    private void readObject(java.io.ObjectInputStream);  
    java.lang.Object writeReplace();  
    java.lang.Object readResolve();  
}  
-keep public class * implements java.io.Serializable {  
    public *;  
}  
  • 如果需要使用Webview的JavaScript interface跟JS交互,JavaScript interface不能混淆
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  public *;
}

ProGuard文件

在release模式下打包apk时会自动运行ProGuard,这里的release模式指的是通过ant release命令或eclipse project->android tools->export signed(unsigned)application package生成apk。在debug模式下为了更快调试并不会调用proguard。如果是ant命令打包apk,proguard信息文件会保存于/bin/proguard文件夹内;如果用eclipse export命令打包,会在/proguard文件夹内。其中包含以下文件:

  • mapping.txt

    表示混淆前后代码的对照表,这个文件非常重要。如果你的代码混淆后会产生bug的话,log提示中是混淆后的代码,希望定位到源代码的话就可以根据mapping.txt反推。
    每次发布都要保留它方便该版本出现问题时调出日志进行排查,它可以根据版本号或是发布时间命名来保存或是放进代码版本控制中。

  • dump.txt

    描述apk内所有class文件的内部结构。

  • seeds.txt

    列出了没有被混淆的类和成员。

  • usage.txt

    列出了源代码中被删除在apk中不存在的代码。

还原 ProGuard 混淆过的代码

利用ProGuard工具混淆后的应用发布到市场上,当有 Crash信息反馈时,开发者看起来就不那么好定位问题了。因为代码信息已经被混淆过了,如:

at com.test.welcome.c.(Unknown Source)
 at com.test.welcome.WelcomeActivity.k(Unknown Source)
 at com.test.welcome.WelcomeActivity.f(Unknown Source)
at com.test.core.activity.BaseCoreMVPActivity.onCreate(Unknown Source)
at com.test.welcome.WelcomeActivity.onCreate(Unknown Source)
at android.app.Activity.performCreate(Activity.java:5459)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2289)

我们可以通过Android本身提供的工具去还原代码信息,该工具位于 /tools/proguard/bin/ 目录下。

  1. 运行 proguardgui.bat(Windows),proguardgui.sh(mac)
  2. 选择ReTrace
  3. 选择mapping文件,输入需要还原的代码
  4. 点击ReTrace按钮

当然也可以通过命令行来还原

retrace.bat/retrace.sh 为命令行工具, 把mapping文件和要还原的混淆信息保存在一个文件中,如stacktrace.txt
然后运行如下命令即可。

./retrace.sh -verbose mapping.txt stacktrace.txt > out.txt

还原后的信息如下:

at com.test.welcome.WelcomePresenter.(Unknown Source)
 at com.test.welcome.WelcomeActivity.createPresenter(Unknown Source)
 at com.test.welcome.WelcomeActivity.createPresenter(Unknown Source)
at com.test.core.activity.BaseCoreMVPActivity.onCreate(Unknown Source)
at com.test.welcome.WelcomeActivity.onCreate(Unknown Source)
at android.app.Activity.performCreate(Activity.java:5459)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2289)

你可能感兴趣的:(android那些事)