安卓混淆和资源压缩

Android开发中掌握混淆规则是必备技能之一。

混淆方式

主module中统一配置

这种情况简单,针对自己项目代码和三方库代码编写混淆规则即可。当取消某些module依赖时,需要剔除响应的混淆规则,较麻烦。

各module单独配置

随着项目不断扩大,多个module同时存在的项目已很普遍。

  • 主module配置一些通用的混淆规则。

  • 子module在gradle中配置consumerProguardFiles属性来指定混淆文件就可以。

    // 子模块单独配置混淆规则
    buildTypes {
          release {
              consumerProguardFiles 'proguard-rules.pro'
          }
      }
      
    

proguard使用及规则

主module开启混淆配置

android {
    ...
    buildTypes {
        release {
              // zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
              zipAlignEnabled true
            // 压缩资源
            shrinkResources true
            // 开启混淆
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}

通用规则

#指定压缩级别
-optimizationpasses 5

#不跳过非公共的库的类成员
-dontskipnonpubliclibraryclassmembers

#混淆时采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#把混淆类中的方法名也混淆了
-useuniqueclassmembernames

#优化时允许访问并修改有修饰符的类和类的成员 
-allowaccessmodification

#将文件来源重命名为“SourceFile”字符串
-renamesourcefileattribute SourceFile
#保留行号
-keepattributes SourceFile,LineNumberTable
#保持泛型
-keepattributes Signature

#保持所有实现 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();
}

#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment


# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    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 * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

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

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

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep ;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep ;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep (...);
}

# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

哪些需要添加keep规则

  • 三方库
  • 反射代码
  • JNI native代码
  • webview js注入方法相关类

自定义规则及语法

  • 不混淆某个类
-keep public class name.huihui.example.Test { *; }
  • 不混淆某个包所有的类
-keep class name.huihui.test.** { *; }
  • 不混淆某个类的子类
-keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有类名中包含了“model”的类及其成员
-keep public class **.*model*.** {*;}
  • 不混淆某个接口的实现
-keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某个类的构造方法
-keepclassmembers class name.huihui.example.Test { 

  ; #匹配所有构造器
  ;#匹配所有域
  ;#匹配所有方法}
  
  public void test(java.lang.String); # 特定方法
  public ;#保持该类下所有的共有方法不被混淆
  public *;#保持该类下所有的共有内容不被混淆
  private ;#保持该类下所有的私有方法不被混淆
  private *;#保持该类下所有的私有内容不被混淆
  public (java.lang.String);#保持该类的String类型的构造方法
}

  • 不混淆某个类的内部类
-keep class name.huihui.example.Test$* {
      *;
}

Thanks

  • Android混淆——了解这些就够了
  • 写给Android开发者的混淆使用手册
  • Proguard实战
  • 官方keep资源

你可能感兴趣的:(安卓混淆和资源压缩)