天天看點

Android Studio 打包混淆

Android Studio預設關閉代碼混淆開關,在build.gradle檔案中,如下所示的minifyEnabled 開關,是以如果需要混淆代碼,需将false改為true,然後在檔案proguard-rules.pro添加具體混淆規則。

build.gradle檔案的buildTypes部分
android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.litepaldemo.test"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled true// 是否進行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'// 混淆檔案的位置
        }
    }
}
           
常用混淆規則如下:

-dontskipnonpubliclibraryclasses # 不忽略非公共的庫類
-optimizationpasses 5            # 指定代碼的壓縮級别
-dontusemixedcaseclassnames      # 是否使用大小寫混合
-dontpreverify                   # 混淆時是否做預校驗
-verbose                         # 混淆時是否記錄日志
-keepattributes *Annotation*     # 保持注解
-ignorewarning                   # 忽略警告
-dontoptimize                    # 優化不優化輸入的類檔案

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

#保持哪些類不被混淆
-keep public class * extends android.app.Activity      
-keep public class * extends android.app.Application   
-keep public class * extends android.app.Service       
-keep public class * extends android.content.BroadcastReceiver  
-keep public class * extends android.content.ContentProvider    
-keep public class * extends android.app.backup.BackupAgentHelper 
-keep public class * extends android.preference.Preference        
-keep public class com.android.vending.licensing.ILicensingService    

#生成日志資料,gradle build時在本項目根目錄輸出
-dump class_files.txt            #apk包内所有class的内部結構
-printseeds seeds.txt            #未混淆的類和成員
-printusage unused.txt           #列印未被使用的代碼
-printmapping mapping.txt        #混淆前後的映射

-keep public class * extends android.support.** #如果有引用v4或者v7包,需添加
-libraryjars libs/xxx.jar        #混淆第三方jar包,其中xxx為jar包名
-keep class com.xxx.**{*;}       #不混淆某個包内的所有檔案
-dontwarn com.xxx**              #忽略某個包的警告
-keepattributes Signature        #不混淆泛型
-keepnames class * implements java.io.Serializable #不混淆Serializable

-keepclassmembers class **.R$* { #不混淆資源類
  public static <fields>;
}
-keepclasseswithmembernames class * {  # 保持 native 方法不被混淆
    native <methods>;
}
-keepclasseswithmembers class * {      # 保持自定義控件類不被混淆
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {      # 保持自定義控件類不被混淆
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity { # 保持自定義控件類不被混淆   
    public void *(android.view.View);
}
-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 *;
}
           

需要打開app子產品下的 proguard-rules.pro 檔案來定義項目打包的混淆選項:

#--------------------------1.實體類---------------------------------
# 如果使用了Gson之類的工具要使被它解析的JavaBean類即實體類不被混淆。(這裡填寫自己項目中存放bean對象的具體路徑)
-keep class com.wiwide.soldout.bean.**{*;}

#--------------------------2.第三方包-------------------------------

#Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.gson.* { *;}
-dontwarn com.google.gson.**

#butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

#-------------------------3.與js互相調用的類------------------------


#-------------------------4.反射相關的類和方法----------------------


#-------------------------5.基本不用動區域--------------------------
#指定代碼的壓縮級别
-optimizationpasses 5

#包明不混合大小寫
-dontusemixedcaseclassnames

#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

#混淆時是否記錄日志
-verbose

#優化  不優化輸入的類檔案
-dontoptimize

#預校驗
-dontpreverify

# 保留sdk系統自帶的一些内容 【例如:-keepattributes *Annotation* 會保留Activity的被@override注釋的onCreate、onDestroy方法等】
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

# 記錄生成的日志資料,gradle build時在本項根目錄輸出
# apk 包内所有 class 的内部結構
-dump proguard/class_files.txt
# 未混淆的類和成員
-printseeds proguard/seeds.txt
# 列出從 apk 中删除的代碼
-printusage proguard/unused.txt
# 混淆前後的映射
-printmapping proguard/mapping.txt


# 避免混淆泛型
-keepattributes Signature
# 抛出異常時保留代碼行号,保持源檔案以及行号
-keepattributes SourceFile,LineNumberTable

#-----------------------------6.預設保留區-----------------------
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclassmembers public class * extends android.view.View {
 public <init>(android.content.Context);
 public <init>(android.content.Context, android.util.AttributeSet);
 public <init>(android.content.Context, android.util.AttributeSet, int);
 public void set*(***);
}

#保持 Serializable 不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# 保持自定義控件類不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet);
}
# 保持自定義控件類不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet,int);
}
# 保持自定義控件類不被混淆
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

# 保持枚舉 enum 類不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

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

# 不混淆R檔案中的所有靜态字段,我們都知道R檔案是通過字段來記錄每個資源的id的,字段名要是被混淆了,id也就找不着了。
-keepclassmembers class **.R$* {
    public static <fields>;
}

#如果引用了v4或者v7包
-dontwarn android.support.**

# 保持哪些類不被混淆
-keep public class * extends android.app.Appliction
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference

-keep class com.zhy.http.okhttp.**{*;}
-keep class com.wiwide.util.** {*;}

# ============忽略警告,否則打包可能會不成功=============
-ignorewarnings