What is ProGuard?

You can think of ProGuard as a tool for code and resource compression that provides compression, optimization, obfuscation, and prevalidation of Java class files. The compression step is to detect and remove unused classes, fields, methods, and properties. The optimization step is to analyze and optimize the bytecode of the method. The confusing step is to rename the remaining classes, fields, and methods with short, meaningless names. Compression, optimization, and obfuscation make code smaller and more efficient.

How does AndroidStudio use ProGuard?

Code compression

To enable code compression with ProGuard, add minifyEnabled True to the corresponding build type in the build.gradle file.

  android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                   'proguard-rules.pro'}}Copy the code

ProGuard removes all (and only) unused code. However, ProGuard is difficult to analyze correctly in many cases and can remove code that your application really needs. For example, in cases where reflection is required or referenced classes are dynamically loaded, ProGuard can cause errors by removing or confusing unused classes. So sometimes you need to write obfuscation optimization profiles. ProguardFiles in Gradle allows you to pass File or File path to ProGuard for execution.

Configure ProGuard rules

Now we open the confusion, but no configuration confusion, we can in the build/intermediates/proguard files/proguard – defaults. TXT to view the default configuration, now we can according to the default configuration for the configuration of our project.

  • Analyze the default configuration file 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
    # 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
    # thoroughly if you go this route.
    
    ####################### START #######################
    
    # Algorithm used for confusion (Google Recommendation algorithm)-optimizations ! code/simplification/arithmetic,! code/simplification/cast,! field/*,! class/merging/*# specify the compression level of the code (between 0 and 7, default 5)
    -optimizationpasses 5
    
    # Improve optimization steps
    -allowaccessmodification
    
    The package name is case-insensitive
    -dontusemixedcaseclassnames
    
    Do not ignore non-public library classes
    -dontskipnonpubliclibraryclasses
    
    Print obfuscation logs
    -verbose
    
    Keep classes required by Google native services unconfused
    -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
    Second, keep native methods from being confused
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    # Keep setters in Views so that animations can still work.
    Keep custom controls (inherited from Views) unconfused
    -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.
    The method parameter to keep in the Activity is the view method (avoid affecting onClick in the layout file).
    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
    }
    
    # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
    Keep the enumeration enum class from being confused
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    # keep Parcelable serialized classes from being confused
    -keepclassmembers class * implements android.os.Parcelable {
        public static final ** CREATOR;
    }
    
    Keep all classes and methods under R(resource) unconfused
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    # Preserve annotated Javascript interface methods.
    -keepclassmembers class * {
        @android.webkit.JavascriptInterface <methods>;
    }
    
    The support library contains references to more recent versions.
    # Do not warn those cases where this app links to old ones
    # Platform version. We know they're safe.
    -dontnote android.support.**
    -dontnote androidx.**
    -dontwarn android.support.**
    -dontwarn androidx.**
    
    This class is deprecated, but backward compatibility remains.
    -dontwarn android.util.FloatMath
    
    # Support package rule
    # 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 * {*; }Keep members of the support Keep class unconfused
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <methods>;
    }
    
    Keep members of the Androidx Keep class from being confused
    -keepclasseswithmembers class * {
        @androidx.annotation.Keep <methods>;
    }
    
    Keep members of the support Keep class unconfused
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <fields>;
    }
    
    Keep members of the Androidx Keep class from being confused
    -keepclasseswithmembers class * {
        @androidx.annotation.Keep <fields>;
    }
    
    Do not obfuscate initialization methods that use annotations in all classes and their class members-keepclasseswithmembers class * { @android.support.annotation.Keep <init>(...) ; }Do not obfuscate initialization methods that use annotations in all classes and their class members-keepclasseswithmembers class * { @androidx.annotation.Keep <init>(...) ; }# excluding android. The jar and org. Apache. HTTP. Legacy. Repeat between jar
    -dontnote org.apache.http.**
    -dontnote android.net.http.**
    
    # Exclude duplication between Android.jar and core-lambda-stubs.jar.
    -dontnote java.lang.invoke.**
    
    Copy the code

So that’s the default configuration file so what exactly does this APK look like? Let’s put a picture here.

Found that the above class has become difficult to read the class. Let’s take a look at Proguard configuration in isolation

Basic instructions
  • Specify the compression level of the code (between 0 and 7, default is 5)

    -optimizationpasses 5
    Copy the code

  • Whether to use mixed case (Windows is case-insensitive, recommended)

    -dontusemixedcaseclassnames
    Copy the code

  • Whether to confuse classes for non-public libraries

    -dontskipnonpubliclibraryclasses
    Copy the code

  • Whether to confuse members of classes that are not public libraries

    -dontskipnonpubliclibraryclassmembers
    Copy the code

  • Whether to perform precheck when obfuscation occurs (Android does not require precheck, removing it can speed up obfuscation)

    -dontpreverify
    Copy the code

  • Whether to log when obfuscation occurs (mapping files are generated after obfuscation)

    -verbose
    Copy the code

  • Specifies an external fuzzy dictionary

    -obfuscationdictionary dictionary_path
    Copy the code

  • Specifies the class fuzzy dictionary

    -classobfuscationdictionary dictionary_path
    Copy the code

  • Specify the Package fuzzy dictionary

    -packageobfuscationdictionary dictionary_path
    Copy the code

  • The algorithm used in confusion (Google Recommendation algorithm)

    -optimizations ! code/simplification/arithmetic,! field/,! class/merging/,! code/allocation/variableCopy the code

  • Add supported jars (import all jar packages under LIBS)

    -libraryjars libs(*.jar;)
    Copy the code

  • Rename the file source to SourceFile “string

    -renamesourcefileattribute SourceFile
    Copy the code

  • Keep annotations unconfused

    -keepattributes Annotation -keep class * extends java.lang.annotation.Annotation {*; } -keep interface * extends java.lang.annotation.Annotation { *; }Copy the code

  • Keep generics from being confused

    -keepattributes Signature-keep class * extends java.lang.annotation.Annotation {*; }Copy the code

  • Keep reflexes from being confused

    -keepattributes EnclosingMethod
    Copy the code

  • Keep exceptions from being confused

    -keepattributes Exceptions
    Copy the code

  • Keep inner classes from being confused

    -keepattributes InnerClasses
    Copy the code

  • Keep the line number when an exception is thrown

    -keepattributes SourceFile,LineNumberTable
    Copy the code

Keep Command Description
instruction instructions
-keep Keep classes and class members from being removed or renamed
-keepnames Keep classes and class members from being renamed
-keepclassmembers Keep class members from being removed or renamed
-keepclassmembernames Keep class members from being renamed
-keepclasseswithmembers Preserves the class and member that owns the member, preventing it from being removed or renamed
-keepclasseswithmembernames Keep the class and member that owns the member from being renamed
  • The format of commands to keep elements from participating in obfuscation rules:

    [Hold command] [class] {[member]} Concrete class access modifier (public, protected, private) wildcard *, matching any length of characters, but without package name delimiter (.) The wildcard character ** matches characters of any length and contains the package name delimiter (.) Extends, which specifies a class's base class Implement, matches a class $that implements an interface. The inner class "member" represents a class member-related qualification that will eventually locate some class member that meets that qualification. Its contents can be used as follows: <init> matches all constructors <fields> matches all fields <methods> Matches all method wildcards *, matches characters of any length, but does not contain package name delimiters (.) The wildcard character ** matches characters of any length and contains the package name delimiter (.) Wildcard *** matches any parameter type... Matches any type of argument of any length. Such as voidtest(...). I can match any voidtest(String A) or voidtest(int a, String b) these methods. Access modifiers (public, protected, private)Copy the code

  • Don’t mess with a class

      -keep public class com.example.proxy_core.ProxyApplication { *; }
    Copy the code

  • Do not confuse all classes of a package

      -keep public class com.example.proxy_core.** { *; }
    Copy the code

  • Do not confuse subclasses of a class

      -keep public class * extends class 
    Copy the code

com.example.proxy_core.ProxyApplication { *; } ` ` `

  • Do not confuse all classes whose class names contain Model and their members

    -keep public class **.*model*.** {*; }Copy the code

  • Do not confuse the implementation of an interface

      -keep class * implements com.example.proxy_core.LoadCallBack { *; }
    Copy the code

  • Do not confuse specific methods of a class

      -keepclassmembers class com.example.proxy_core.ProxyApplication {
           public void getVersion(java.lang.String);
      }
    Copy the code

  • Do not confuse inner classes of a class

        -keep class com.example.proxy_core.ProxyApplication$* {
           *;
      }
    Copy the code

Precautions for Proguard
  • The basic components are not confused

    -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.PreferenceCopy the code

  • Keep the classes required by Google’s native services from being confused

      -keep public class com.google.vending.licensing.ILicensingService
      -keep public class com.android.vending.licensing.ILicensingService
    Copy the code

  • The Support package rules

      -dontwarn android.support.**
      -keep public class * extends android.support.v4.**
      -keep public class * extends android.support.v7.**
      -keep public class * extends android.support.annotation.**
    Copy the code

  • Keep native methods from being confused

      -keepclasseswithmembernames class * {
          native <methods>;
      }
    Copy the code

  • Leave custom controls (inherited from Views) unconfused

      -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); }Copy the code

  • Leave the constructor of the specified format unconfused

      -keepclasseswithmembers class * {
          public <init>(android.content.Context, android.util.AttributeSet);
          public <init>(android.content.Context, android.util.AttributeSet, int);
      }
    Copy the code

  • Method parameters retained in the Activity are view methods (to avoid affecting onClick in the layout file)

      -keepclassmembers class * extends android.app.Activity {
          public void *(android.view.View);
      }
    Copy the code

  • Keep enumeration enum classes from being confused

      -keepclassmembers enum * {
          public static **[] values();
          public static ** valueOf(java.lang.String);
      }
    Copy the code

  • Keep all classes and their methods under R (resource) unconfused

      -keep class **.R$* { *; }
    Copy the code

  • Keep Parcelable serialized classes from being confused (note: aiDL files cannot be confused)

      -keep class * implements android.os.Parcelable {
           public static final android.os.Parcelable$Creator *;
      }
    Copy the code

  • Classes that need to be serialized and deserialized cannot be confused (note: Classes used by Java reflection cannot be confused either)

      -keepnames class * implements java.io.Serializable
    Copy the code

  • Keep Serializable class members from being confused

    -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 voidreadObject(java.io.ObjectInputStream);
         java.lang.Object writeReplace();
          java.lang.Object readResolve();
      }
    Copy the code

  • Keep Adapter classes from being confused

      -keep public class * extends android.widget.BaseAdapter { *; }
    Copy the code

  • Keep the CusorAdapter class from being confused

      -keep public class * extends android.widget.CusorAdapter{ *; }
    Copy the code

Write basic common version obfuscation rules

# 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
# 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
# thoroughly if you go this route.
# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- basic instruction area -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- # specified code compression level (between 0 ~ 7, defaults to 5)
-optimizationpasses 5
# Whether to use mixed case (Windows case is not sensitive, recommended to add)
-dontusemixedcaseclassnames
 Whether to confuse classes for non-public libraries
-dontskipnonpubliclibraryclasses
Whether to confuse members of non-public library classes
-dontskipnonpubliclibraryclassmembers
Android does not require prevalidation. Remove it to speed up the obfuscation.
-dontpreverify
Whether to log the obfuscation (map files will be generated after the obfuscation)
-verbose

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if you have add # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# specify an external blur dictionary
-obfuscationdictionary dictionary1.txt
# specify class fuzzy dictionary
-classobfuscationdictionary dictionary1.txt
# specify package ambiguity dictionary
-packageobfuscationdictionary dictionary2.txt
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Algorithm used for confusion (Google Recommendation algorithm)-optimizations ! code/simplification/arithmetic,! field/*,! class/merging/*,! code/allocation/variable# add supported JARS (add all jar packages under LIBS)
-libraryjars libs(*.jar;)

# rename file source to "SourceFile" string
-renamesourcefileattribute SourceFile

Keep annotations unconfused-keepattributes *Annotation* -keep class * extends java.lang.annotation.Annotation {*; }Keep generics from being confused
-keepattributes Signature
# Keep reflection unconfused
-keepattributes EnclosingMethod
Keep exceptions from being confused
-keepattributes Exceptions
Keep inner classes from being confused
-keepattributes Exceptions,InnerClasses
Keep the line number when throwing an exception
-keepattributes SourceFile,LineNumberTable

# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the default reserves -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - #
Keep basic components unconfused-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.PreferenceKeep classes required by Google native services unconfused
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# Support package rule
-dontwarn android.support.**
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

# Keep native methods unconfused
-keepclasseswithmembernames class * {
    native <methods>;
}

Keep custom controls (inherited from Views) unconfused
-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); }Leave the constructor of the specified format unconfused
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

The method parameter to keep in the Activity is the view method (avoid affecting onClick in the layout file).
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

Keep the enumeration enum class from being confused
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

Keep all classes and methods under R(resource) unconfused
-keep class **.R$* { *; }

# keep Parcelable serialized classes from being confused
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

Classes that need to be serialized and deserialized cannot be confused.
-keepnames class * implements java.io.Serializable

Keep Serializable class members from being confused-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 voidreadObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

Keep the BaseAdapter class unconfused
-keep public class * extends android.widget.BaseAdapter { *; }
Keep the CusorAdapter class from being confused
-keep public class * extends android.widget.CusorAdapter{ *; }

# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the webView area -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- #
# WebView processing, the project does not use WebView can be ignored
Keep Android classes that interact with JavaScript unconfused
-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);
}

# Network request correlation
-keep public class android.net.http.SslError

# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- delete code area -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - #
# delete log-related code from code-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(...) ; }Copy the code

Obfuscation rules required by third parties

################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(a); } -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
Copy the code

Obfuscated code error stack recovery method
  1. The outputs/mapping/debug/mapping. TXT file (save) the relation between before and after the confusion.
  2. Use the SDK tools/tools/groguard/bin/retrace. Bat configuration – first keepattributes SourceFile, LineNumberTable perform retrace. Bat – verbose mappint File Bug file

Resources compression

Resource compression only works in conjunction with code compression. After the code compressor removes all unused code, the resource compressor can determine which resources are still being used by the application. This is especially true when you add a code base that contains resources – you must remove unused library code to make library resources unreferenced before you can remove them through the resource compressor

To enable resource compression, set the shrinkResources property to true in the build.gradle file (next to minifyEnabled for code compression). Such as:

  android {
      ...
      buildTypes {
          release {
              shrinkResources true
              minifyEnabled true
              proguardFiles getDefaultProguardFile('proguard-android.txt'),
                      'proguard-rules.pro'}}}Copy the code

If you haven’t already built your application with minifyEnabled for code compression, try using it first and then enabling shrinkResources, as you may need to edit the ProGuard-rules.pro file to preserve classes or methods that are dynamically created or called, Then start removing resources.

Remove unused spare resources
  • Remove support only For Chinese and English

      android {
          defaultConfig {
              ...
              resConfigs "zh"."en"}}Copy the code

  • Merging duplicate resources

    By default, Gradle also merges resources with the same name, such as drawable objects that may reside in different resource folders. This behavior is not controlled by the shrinkResources property and cannot be disabled because it is necessary to avoid errors when there are multiple resources matching the name the code is looking for.

    A resource merge occurs only if two or more files have exactly the same resource name, type, and qualifier. Gradle selects the file it considers the best choice from the duplicates (in the order of priority below) and passes only this one resource to AAPT for distribution in APK files.

    Gradle looks for duplicate resources in the following locations:

    • The primary resource associated with the primary source set, typically locatedsrc/main/res/In the.
    • Variant overlay, from build types and build flavors.
    • Library project dependencies.

    Gradle merges duplicate resources in descending order:

    Dependencies → Main resource → Build flavor → Build type

    For example, if a repeating resource is present in both the main resource and the build flavor, Gradle selects the repeating resource in the build flavor.

    If exactly the same resources appear in the same source set, Gradle cannot merge them and will issue a resource merge error. This can happen if you define multiple source sets in the sourceSet property of your build.gradle file, for example, if SRC /main/res/ and SRC /main/res2/ contain exactly the same resources.

  • Check the resource compression problem

    When you compress resources, Gradle Console displays a summary of the resources it has removed from the application package. Such as:

    :android:shrinkDebugResources Removed unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33% :android:validateDebugSigning
    Copy the code

Gradle in < module name > / build/outputs/mapping/release/(ProGuard output file in folder) to create a named resources. The diagnosis of TXT file. This file includes details such as which resources reference other resources and which resources are used or removed.