性能優化 (十一) ProGuard 對代碼和資源壓縮

性能優化系列

APP 啓動優化html

UI 繪製優化java

內存優化react

圖片壓縮android

長圖優化web

電量優化算法

Dex 加解密apache

動態替換 Applicationwindows

APP 穩定性之熱修復原理探索安全

APP 持續運行之進程保活實現性能優化

ProGuard 對代碼和資源壓縮

APK 極限壓縮

ProGuard 是什麼?

能夠把 ProGuard 理解爲是對代碼和資源壓縮的一個工具,它可以提供對 Java 類文件的壓縮、優化、混淆,和預校驗。壓縮的步驟是檢測並移除未使用的類、字段、方法和屬性。優化的步驟是分析和優化方法的字節碼。混淆的步驟是使用短的毫無心義的名稱重命名剩餘的類、字段和方法。壓縮、優化、混淆使得代碼更小,更高效。

AndroidStudio 怎麼使用 ProGuard ?

代碼壓縮

要經過 ProGuard 啓用代碼壓縮,請在 build.gradle 文件內相應的構建類型中添加 minifyEnabled true

android {
    ...
    buildTypes {
        release {
            minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } 複製代碼

ProGuard 會移除全部 (而且只會移除) 未使用的代碼。不過 , ProGuard 難以對許多狀況進行正確分析,可能會移除應用真正須要的代碼。好比須要反射、動態加載所引用的類等狀況,可能由於ProGuard 移除或者混淆了這部分沒使用的類,而致使錯誤。因此有時須要編寫混淆優化配置文件。在 gradle 中的 proguardFiles 可以讓咱們傳遞File文件或者文件路徑交給 proguard 來執行。

配置 ProGuard 規則

如今咱們開啓了混淆,可是尚未配置混淆,咱們能夠在 build/intermediates/proguard-files/proguard-defaults.txt 來查看默認的配置,如今咱們能夠根據默認的配置來進行咱們項目的配置。

  • 分析默認配置文件 proguard-defaults.txt-3.4.0

    # This is a configuration file for ProGuard.
    # http://proguard.sourceforge.net/index.html#manual/usage.html
    #
    # Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
    # the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
    # will be ignored by new version of the Android plugin for Gradle.
    
    # Optimizations can be turned on and off in the 'postProcessing' DSL block.
    # The configuration below is applied if optimizations are enabled.
    # Adding optimization introduces certain risks, since for example not all optimizations performed by
    # ProGuard works on all versions of Dalvik.  The following flags turn off various optimizations
    # known to have issues, but the list may not be complete or up to date. (The "arithmetic"
    # optimization can be used if you are only targeting Android 2.0 or later.)  Make sure you test
    # thoroughly if you go this route.
    
    ####################### START #######################
    
    # 混淆時所採用的算法(谷歌推薦算法)
    -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
    
    # 指定代碼的壓縮級別(在0~7之間,默認爲5)
    -optimizationpasses 5
    
    # 提升優化步驟
    -allowaccessmodification
    
    # 包名不混合大小寫
    -dontusemixedcaseclassnames
    
    # 不忽略非公共的庫類
    -dontskipnonpubliclibraryclasses
    
    # 輸出混淆日誌
    -verbose
    
    # 保持 Google 原生服務須要的類不被混淆
    -keep public class com.google.vending.licensing.ILicensingService
    -keep public class com.android.vending.licensing.ILicensingService
    -keep public class com.google.android.vending.licensing.ILicensingService
    -dontnote com.android.vending.licensing.ILicensingService
    -dontnote com.google.vending.licensing.ILicensingService
    -dontnote com.google.android.vending.licensing.ILicensingService
    
    # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
    # 混淆注意事項第二條,保持 native 方法不被混淆
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    # Keep setters in Views so that animations can still work.
    # 保留自定義控件(繼承自View)不被混淆
    -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.
    # 保留在 Activity 中的方法參數是 view 的方法(避免佈局文件裏面 onClick 被影響)
    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
    }
    
    # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
    # 保持枚舉 enum 類不被混淆
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    # 保持 Parcelable 序列化的類不被混淆(注:aidl 文件不能去混淆)
    -keepclassmembers class * implements android.os.Parcelable {
        public static final ** CREATOR;
    }
    
    # 保持R(資源)下的全部類及其方法不能被混淆
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    # Preserve annotated Javascript interface methods.
    -keepclassmembers class * {
        @android.webkit.JavascriptInterface <methods>;
    }
    
    # 支持庫包含對較新版本版本的引用。
    # 不要警告那些狀況下,這個應用程序連接到舊的
    # 平臺版本。咱們知道他們是安全的。
    -dontnote android.support.**
    -dontnote androidx.**
    -dontwarn android.support.**
    -dontwarn androidx.**
    
    # 此類已棄用,但仍保留向後兼容性。
    -dontwarn android.util.FloatMath
    
    # Support包規則
    # Understand the @Keep support annotation.
    -keep class android.support.annotation.Keep
    -keep class androidx.annotation.Keep
    
    -keep @android.support.annotation.Keep class * {*;}
    -keep @androidx.annotation.Keep class * {*;}
    
    # 保持 support Keep 類成員不被混淆
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <methods>;
    }
    
    # 保持 androidx Keep 類成員不被混淆
    -keepclasseswithmembers class * {
        @androidx.annotation.Keep <methods>;
    }
    
    # 保持 support Keep 類成員不被混淆
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <fields>;
    }
    
    # 保持 androidx Keep 類成員不被混淆
    -keepclasseswithmembers class * {
        @androidx.annotation.Keep <fields>;
    }
    
    # 不混淆全部類及其類成員中的使用註解的初始化方法
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <init>(...);
    }
    
    # 不混淆全部類及其類成員中的使用註解的初始化方法
    -keepclasseswithmembers class * {
        @androidx.annotation.Keep <init>(...);
    }
    
    # 排除 android.jar 和 org.apache.http.legacy.jar 之間重複
    -dontnote org.apache.http.**
    -dontnote android.net.http.**
    
    # 排除 android.jar 和核心-lambda-stubs.jar 之間重複。
    -dontnote java.lang.invoke.**
    
    複製代碼

    以上就是默認配置文件那麼這樣生成出來的 APK 究竟是什麼樣的勒?下面放上一張圖片來看下。

    發現上面的 類 已經變成不易閱讀的類了。下面咱們就來單獨分析下 Proguard 的配置

基本指令
  • 指定代碼的壓縮級別(在0~7之間,默認爲5)

    -optimizationpasses 5
    複製代碼
  • 是否使用大小寫混合(windows大小寫不敏感,建議加入)

    -dontusemixedcaseclassnames
    複製代碼
  • 是否混淆非公共的庫的類

    -dontskipnonpubliclibraryclasses
    複製代碼
  • 是否混淆非公共的庫的類的成員

    -dontskipnonpubliclibraryclassmembers
    複製代碼
  • 混淆時是否作預校驗(Android不須要預校驗,去掉能夠加快混淆速度)

    -dontpreverify
    複製代碼
  • 混淆時是否記錄日誌(混淆後會生成映射文件)

    -verbose
    複製代碼
  • 指定外部模糊字典

    -obfuscationdictionary dictionary_path
    複製代碼
  • 指定 class 模糊字典

    -classobfuscationdictionary dictionary_path
    複製代碼
  • 指定 package 模糊字典

    -packageobfuscationdictionary dictionary_path
    複製代碼
  • 混淆時所採用的算法(谷歌推薦算法)

    -optimizations !code/simplification/arithmetic,!field/,!class/merging/,!code/allocation/variable 複製代碼
  • 添加支持的jar(引入libs下的全部jar包)

    -libraryjars libs(*.jar;) 複製代碼
  • 將文件來源重命名爲 SourceFile」`字符串

    -renamesourcefileattribute SourceFile
    複製代碼
  • 保持註解不被混淆

    -keepattributes Annotation
    -keep class * extends java.lang.annotation.Annotation {*;}
    -keep interface * extends java.lang.annotation.Annotation { *; }
    複製代碼
  • 保持泛型不被混淆

    -keepattributes Signature-keep class * extends java.lang.annotation.Annotation {*;}
    複製代碼
  • 保持反射不被混淆

    -keepattributes EnclosingMethod
    複製代碼
  • 保持異常不被混淆

    -keepattributes Exceptions
    複製代碼
  • 保持內部類不被混淆

    -keepattributes InnerClasses
    複製代碼
  • 拋出異常時保留代碼行號

    -keepattributes SourceFile,LineNumberTable
    複製代碼
keep 命令說明
指令 說明
-keep 保持類和類成員,防止被移除或者被重命名
-keepnames 保持類和類成員,防止被重命名
-keepclassmembers 保持類成員,防止被移除或者被重命名
-keepclassmembernames 保持類成員,防止被重命名
-keepclasseswithmembers 保持擁有該成員的類和成員,防止被移除或者被重命名
-keepclasseswithmembernames 保持擁有該成員的類和成員,防止被重命名
  • 保持元素不參與混淆的規則的命令格式:

    [保持命令] [類] {
        [成員]
    }
    
    具體的類
    訪問修飾符(publicprotectedprivate)
    通配符*,匹配任意長度字符,但不含包名分隔符(.)
    通配符**,匹配任意長度字符,而且包含包名分隔符(.)
    extends,便可以指定類的基類
    implement,匹配實現了某接口的類
    $,內部類
    「成員」表明類成員相關的限定條件,它將最終定位到某些符合該限定條件的類成員。它的內容可使用:
    <init> 匹配全部構造器
    <fields> 匹配全部域
    <methods> 匹配全部方法
    通配符*,匹配任意長度字符,但不含包名分隔符(.)
    通配符**,匹配任意長度字符,而且包含包名分隔符(.)
    通配符***,匹配任意參數類型
    …,匹配任意長度的任意類型參數。好比void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 這些方法。 訪問修飾符(publicprotectedprivate複製代碼
  • 不混淆某個類

    -keep public class com.example.proxy_core.ProxyApplication { *; }
    複製代碼
  • 不混淆某個包全部的類

    -keep public class com.example.proxy_core.** { *; }
    複製代碼
  • 不混淆某個類的子類

    -keep public class * extends class com.example.proxy_core.ProxyApplication { *; }
    複製代碼
  • 不混淆全部類名中包含了 model的類及其成員

    -keep public class **.*model*.** {*;}
    複製代碼
  • 不混淆某個接口的實現

    -keep class * implements com.example.proxy_core.LoadCallBack { *; }
    複製代碼
  • 不混淆某個類的特定的方法

    -keepclassmembers class com.example.proxy_core.ProxyApplication {
         public void getVersion(java.lang.String);
    }
    複製代碼
  • 不混淆某個類的內部類

    -keep class com.example.proxy_core.ProxyApplication$* {
           *;
    }
    複製代碼
Proguard 注意事項
  • 基本組件不被混淆

    -keep public class * extends android.app.Fragment -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 複製代碼
  • 保持 Google 原生服務須要的類不被混淆

    -keep public class com.google.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService 複製代碼
  • Support 包規則

    -dontwarn android.support.**
    -keep public class * extends android.support.v4.** -keep public class * extends android.support.v7.** -keep public class * extends android.support.annotation.** 複製代碼
  • 保持 native 方法不被混淆

    -keepclasseswithmembernames class * {
        native <methods>;
    }
    複製代碼
  • 保留自定義控件 ( 繼承自 View ) 不被混淆

    -keep public class * extends android.view.View {
         *** get*();
         void set*(***);
         public <init>(android.content.Context);
         public <init>(android.content.Context, android.util.AttributeSet);
         public <init>(android.content.Context, android.util.AttributeSet, int);
        }
    複製代碼
  • 保留指定格式的構造方法不被混淆

    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet);
        public <init>(android.content.Context, android.util.AttributeSet, int);
        }
    
    複製代碼
  • 保留在 Activity 中的方法參數是 view 的方法(避免佈局文件裏面 onClick 被影響)

    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
    }
    複製代碼
  • 保持枚舉 enum 類不被混淆

    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    複製代碼
  • 保持 R (資源)下的全部類及其方法不能被混淆

    -keep class **.R$* { *; }
    複製代碼
  • 保持 Parcelable 序列化的類不被混淆(注:aidl 文件不能去混淆)

    -keep class * implements android.os.Parcelable {
         public static final android.os.Parcelable$Creator *;
    }
    複製代碼
  • 須要序列化和反序列化的類不能被混淆(注:Java 反射用到的類也不能被混淆)

    -keepnames class * implements java.io.Serializable 複製代碼
  • 保持 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();
    }
    
    複製代碼
  • 保持 Adapter 類不被混淆

    -keep public class * extends android.widget.BaseAdapter { *; }
    複製代碼
  • 保持 CusorAdapter 類不被混淆

    -keep public class * extends android.widget.CusorAdapter{ *; }
    複製代碼
編寫基礎通用版本混淆規則
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.

# Optimizations can be turned on and off in the 'postProcessing' DSL block.
# The configuration below is applied if optimizations are enabled.
# Adding optimization introduces certain risks, since for example not all optimizations performed by
# ProGuard works on all versions of Dalvik.  The following flags turn off various optimizations
# known to have issues, but the list may not be complete or up to date. (The "arithmetic"
# optimization can be used if you are only targeting Android 2.0 or later.)  Make sure you test
# thoroughly if you go this route.
# --------------------------------------------基本指令區-------------------------------------------# 指定代碼的壓縮級別(在0~7之間,默認爲5)
-optimizationpasses 5
# 是否使用大小寫混合(windows大小寫不敏感,建議加入)
-dontusemixedcaseclassnames
 # 是否混淆非公共的庫的類
-dontskipnonpubliclibraryclasses
# 是否混淆非公共的庫的類的成員
-dontskipnonpubliclibraryclassmembers
# 混淆時是否作預校驗(Android不須要預校驗,去掉能夠加快混淆速度)
-dontpreverify
# 混淆時是否記錄日誌(混淆後會生成映射文件)
-verbose

###################################### 若是有就添加 ############################################
#指定外部模糊字典
-obfuscationdictionary dictionary1.txt
#指定class模糊字典
-classobfuscationdictionary dictionary1.txt
#指定package模糊字典
-packageobfuscationdictionary dictionary2.txt
#########################################################################################

# 混淆時所採用的算法(谷歌推薦算法)
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable

# 添加支持的jar(引入libs下的全部jar包)
-libraryjars libs(*.jar;)

# 將文件來源重命名爲「SourceFile」字符串
-renamesourcefileattribute SourceFile

# 保持註解不被混淆
-keepattributes *Annotation*
-keep class * extends java.lang.annotation.Annotation {*;}

# 保持泛型不被混淆
-keepattributes Signature
# 保持反射不被混淆
-keepattributes EnclosingMethod
# 保持異常不被混淆
-keepattributes Exceptions
# 保持內部類不被混淆
-keepattributes Exceptions,InnerClasses
# 拋出異常時保留代碼行號
-keepattributes SourceFile,LineNumberTable

# --------------------------------------------默認保留區--------------------------------------------#
# 保持基本組件不被混淆
-keep public class * extends android.app.Fragment
-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

# 保持 Google 原生服務須要的類不被混淆
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# Support包規則
-dontwarn android.support.**
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

# 保留自定義控件(繼承自View)不被混淆
-keep public class * extends android.view.View {
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 保留指定格式的構造方法不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 保留在Activity中的方法參數是view的方法(避免佈局文件裏面onClick被影響)
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

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

# 保持R(資源)下的全部類及其方法不能被混淆
-keep class **.R$* { *; }

# 保持 Parcelable 序列化的類不被混淆(注:aidl文件不能去混淆)
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

# 須要序列化和反序列化的類不能被混淆(注:Java反射用到的類也不能被混淆)
-keepnames class * implements java.io.Serializable

# 保持 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();
}

# 保持 BaseAdapter 類不被混淆
-keep public class * extends android.widget.BaseAdapter { *; }
# 保持 CusorAdapter 類不被混淆
-keep public class * extends android.widget.CusorAdapter{ *; }

# --------------------------------------------webView區--------------------------------------------#
# WebView處理,項目中沒有使用到webView忽略便可
# 保持Android與JavaScript進行交互的類不被混淆
-keep class **.AndroidJavaScript { *; }
-keepclassmembers class * extends android.webkit.WebViewClient {
     public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap);
     public boolean *(android.webkit.WebView,java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebChromeClient {
     public void *(android.webkit.WebView,java.lang.String);
}

# 網絡請求相關
-keep public class android.net.http.SslError

# --------------------------------------------刪除代碼區--------------------------------------------#
# 刪除代碼中Log相關的代碼
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}
複製代碼
第三方須要的混淆規則
################alipay###############

-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}

################retrofit###############
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

################butterknife###############
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
   @butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
 @butterknife.* <methods>;
}


################gson###############
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.sunloto.shandong.bean.** { *; }


################glide###############
-keep public class * implements com.bumptech.glide.module.AppGlideModule
-keep public class * implements com.bumptech.glide.module.LibraryGlideModule
-keep class com.bumptech.glide.** { *; }
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
}

################okhttp###############
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn com.squareup.okhttp.**


################androidEventBus###############
-keep class org.simple.** { *; }
-keep interface org.simple.** { *; }
-keepclassmembers class * {
    @org.simple.eventbus.Subscriber <methods>;
}
-keepattributes *Annotation*


################EventBus###############
-keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep class org.greenrobot.eventbus.EventBus { *; }
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

################autolayout###############
-keep class com.zhy.autolayout.** { *; }
-keep interface com.zhy.autolayout.** { *; }


################RxJava and RxAndroid###############
-dontwarn org.mockito.**
-dontwarn org.junit.**
-dontwarn org.robolectric.**

-keep class io.reactivex.** { *; }
-keep interface io.reactivex.** { *; }

-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-dontwarn okio.**
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**

-dontwarn io.reactivex.**
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
    @retrofit.http.* <methods>;
}

-keep class sun.misc.Unsafe { *; }

-dontwarn java.lang.invoke.*

-keep class io.reactivex.schedulers.Schedulers {
    public static <methods>;
}
-keep class io.reactivex.schedulers.ImmediateScheduler {
    public <methods>;
}
-keep class io.reactivex.schedulers.TestScheduler {
    public <methods>;
}
-keep class io.reactivex.schedulers.Schedulers {
    public static ** test();
}
-keepclassmembers class io.reactivex.internal.util.unsafe.*ArrayQueue*Field* {
    long producerIndex;
    long consumerIndex;
}
-keepclassmembers class io.reactivex.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    long producerNode;
    long consumerNode;
}

-keepclassmembers class io.reactivex.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    io.reactivex.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class io.reactivex.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    io.reactivex.internal.util.atomic.LinkedQueueNode consumerNode;
}

-dontwarn io.reactivex.internal.util.unsafe.**



################espresso###############
-keep class android.support.test.espresso.** { *; }
-keep interface android.support.test.espresso.** { *; }



################annotation###############
-keep class android.support.annotation.** { *; }
-keep interface android.support.annotation.** { *; }


################RxLifeCycle#################
-keep class com.trello.rxlifecycle2.** { *; }
-keep interface com.trello.rxlifecycle2.** { *; }


################RxPermissions#################
-keep class com.tbruyelle.rxpermissions2.** { *; }
-keep interface com.tbruyelle.rxpermissions2.** { *; }

################RxCache#################
-dontwarn io.rx_cache2.internal.**
-keep class io.rx_cache2.internal.Record { *; }
-keep class io.rx_cache2.Source { *; }

-keep class io.victoralbertos.jolyglot.** { *; }
-keep interface io.victoralbertos.jolyglot.** { *; }

################RxErrorHandler#################
 -keep class me.jessyan.rxerrorhandler.** { *; }
 -keep interface me.jessyan.rxerrorhandler.** { *; }

################Timber#################
-dontwarn org.jetbrains.annotations.**


################Canary#################
-dontwarn com.squareup.haha.guava.**
-dontwarn com.squareup.haha.perflib.**
-dontwarn com.squareup.haha.trove.**
-dontwarn com.squareup.leakcanary.**
-keep class com.squareup.haha.** { *; }
-keep class com.squareup.leakcanary.** { *; }

# Marshmallow removed Notification.setLatestEventInfo()
-dontwarn android.app.Notification

複製代碼
混淆後的代碼錯誤棧恢復方法
  1. 把 outputs/mapping/debug/mapping.txt 文件保存 (保存了混淆先後的對應關係)。
  2. 使用工具 sdk/tools/groguard/bin/retrace.bat 先配置 -keepattributes SourceFile,LineNumberTable 再執行 retrace.bat -verbose mappint 文件 bug 文件

資源壓縮

資源壓縮只與代碼壓縮協同工做。代碼壓縮器移除全部未使用的代碼後,資源壓縮器即可肯定應用仍然使用的資源。這在您添加包含資源的代碼庫時體現得尤其明顯 - 您必須移除未使用的庫代碼,使庫資源變爲未引用資源,才能經過資源壓縮器將它們移除

要啓用資源壓縮,請在 build.gradle 文件中將 shrinkResources 屬性設置爲 true(在用於代碼壓縮的 minifyEnabled 旁邊)。例如:

android {
    ...
    buildTypes {
        release {
            shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } 複製代碼

若是您還沒有使用代碼壓縮用途的 minifyEnabled 構建應用,請先嚐試使用它,而後再啓用 shrinkResources,由於您可能須要編輯 proguard-rules.pro 文件以保留動態建立或調用的類或方法,而後再開始移除資源。

移除未使用的備用資源
  • 移除僅支持中文和英語

    android {
        defaultConfig {
            ...
            resConfigs "zh","en"
        }
    }
    複製代碼
  • 合併重複資源

    默認狀況下,Gradle 還會合並同名資源,例如可能位於不一樣資源文件夾中的同名可繪製對象。這一行爲不受 shrinkResources 屬性控制,也沒法停用,由於在有多個資源匹配代碼查詢的名稱時,有必要利用這一行爲來避免錯誤。

    只有在兩個或更多個文件具備徹底相同的資源名稱、類型和限定符時,纔會進行資源合併。Gradle 會在重複項中選擇其視爲最佳選擇的文件(根據下述優先順序),並只將這一個資源傳遞給 AAPT,以供在 APK 文件中分發。

    Gradle 會在下列位置尋找重複資源:

    • 與主源集關聯的主資源,通常位於 src/main/res/ 中。
    • 變體疊加,來自構建類型和構建風味。
    • 庫項目依賴項。

    Gradle 會按如下級聯優先順序合併重複資源:

    依賴項 → 主資源 → 構建風味 → 構建類型

    例如,若是某個重複資源同時出如今主資源和構建風味中,Gradle 會選擇構建風味中的重複資源。

    若是徹底相同的資源出如今同一源集中,Gradle 沒法合併它們,而且會發出資源合併錯誤。若是您在 build.gradle 文件的 sourceSet 屬性中定義了多個源集,則可能會發生這種狀況,例如,若是 src/main/res/src/main/res2/ 包含徹底相同的資源,就可能會發生這種狀況。

  • 排查資源壓縮問題

    當您壓縮資源時,Gradle Console 會顯示它從應用軟件包中移除的資源的摘要。例如:

    :android:shrinkDebugResources Removed unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33% :android:validateDebugSigning
    複製代碼

    Gradle 還會在 <module-name>/build/outputs/mapping/release/(ProGuard 輸出文件所在的文件夾)中建立一個名爲 resources.txt 的診斷文件。該文件包括諸如哪些資源引用了其餘資源以及使用或移除了哪些資源等詳情。

感謝:

壓縮代碼和資源

相關文章
相關標籤/搜索