1. 程式人生 > >Android 混淆 (不定期完善第三方混淆規則)

Android 混淆 (不定期完善第三方混淆規則)

開啟混淆

在AS中,藉助於SDK中自帶的Proguard工具,開啟混淆只需要在release閉包中新增如下兩行程式碼:

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

其中minifyEnabled表示是否開啟混淆,開啟後打包出的apk就是混淆過的了。

有些程式碼如果被混淆了就會報錯,因此需要混淆規則來定義那些不能混淆的程式碼。

proguard-android.txt是預設的混淆規則,該檔案位於fake-path—sdk\tools\proguard目錄下,它對本機上所有專案的混淆都生效,所以一般不改動這個檔案。

proguard-rules.pro預設在每個專案的app模組中,我們可以在這個檔案中編寫適用於當前專案的混淆規則。

預設情況下,這樣的寫法會使兩個檔案中的混淆規則同時生效。

混淆語法

keep關鍵字

proguard中一共有三組六個keep關鍵字,區別如下:

關鍵字 描述
keep 保留類和類中的成員,防止它們被混淆或移除。
keepnames 保留類和類中的成員,防止它們被混淆,但當成員沒有被引用時會被移除。
keepclassmembers 只保留類中的成員,防止它們被混淆或移除。
keepclassmembernames 只保留類中的成員,防止它們被混淆,但當成員沒有被引用時會被移除。
keepclasseswithmembers 保留類和類中的成員,防止它們被混淆或移除,前提是指名的類中的成員必須存在,如果不存在則還是會混淆。
keepclasseswithmembernames 保留類和類中的成員,防止它們被混淆,但當成員沒有被引用時會被移除,前提是指名的類中的成員必須存在,如果不存在則還是會混淆。

萬用字元

萬用字元 描述
<field> 匹配類中的所有欄位
<method> 匹配類中的所有方法
<init> 匹配類中的所有建構函式
* 匹配任意長度字元,但不含包名分隔符(.)。但如果你不寫任何其它內容,只有一個*,那就表示匹配所有的東西。
** 匹配任意長度字元,並且包含包名分隔符(.),包括任意長度的子包。
*** 匹配任意引數型別。比如void set*()就能匹配任意傳入的引數型別, get*()就能匹配任意返回值的型別。
匹配任意長度的任意型別引數。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)這些方法。

預設混淆規則

下面是proguard-android.txt檔案中的內容(手動加了註釋):

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

#混淆時不使用大小寫混合類名。 
-dontusemixedcaseclassnames

#不跳過library中的非public的類。 
-dontskipnonpubliclibraryclasses

#混淆後產生對映檔案
#包含有類名->混淆後類名的對映關係
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).

#不進行優化,建議使用此選項,因為根據proguard-android-optimize.txt中的描述,優化可能會造成一些潛在風險,不能保證在所有版本的Dalvik上都正常執行。 
-dontoptimize

#不進行預校驗。這個預校驗是作用在Java平臺上的,Android平臺上不需要這項功能,去掉之後還可以加快混淆速度。
-dontpreverify

# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

#對註解中的引數進行保留。
-keepattributes *Annotation*

#不混淆宣告的這兩個類,這兩個類我們基本也用不上,是接入Google原生的一些服務時使用的。
-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

#不混淆任何包含native方法的類的類名以及native方法名,但當成員沒有被引用時會被移除
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans

#不混淆任何一個View中的setXxx()和getXxx()方法,因為屬性動畫需要有相應的setter和getter的方法實現,混淆了就無法工作了。
-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的方法,因為有這樣一種用法,在XML中配置android:onClick=”buttonClick”屬性,當用戶點選該按鈕時就會呼叫Activity中的buttonClick(View view)方法,如果這個方法被混淆的話就找不到了。
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations

#不混淆列舉中的values()和valueOf()方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#不混淆Parcelable實現類中的CREATOR欄位,毫無疑問,CREATOR欄位是絕對不能改變的,包括大小寫都不能變,不然整個Parcelable工作機制都會失敗。
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

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

# 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.

#對android.support包下的程式碼不警告,因為相容庫的中程式碼是安全的
-dontwarn android.support.**

# Understand the @Keep support annotation.

#不混淆keep註解
-keep class android.support.annotation.Keep

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

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

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

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

自定義混淆規則

我們可以在當前專案的proguard-rules.pro中定義如下混淆規則,其中第三方混淆規則將不定期更新、完善:

##---------------Begin: proguard configuration common for all Android apps ----------
#程式碼混淆壓縮比,在0~7之間,預設為5,一般不做修改
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt
#指定混淆採用的演算法,後面的引數是一個過濾器
#這個過濾器是谷歌推薦的演算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*


-allowaccessmodification
-keepattributes *Annotation*
-renamesourcefileattribute SourceFile
#丟擲異常時保留程式碼行號
-keepattributes SourceFile,LineNumberTable
-repackageclasses ''

#保留我們使用的四大元件,自定義的Application等這些子類不被混淆
#因為這些子類都有可能被外部呼叫
-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
-dontnote com.android.vending.licensing.ILicensingService


# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-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();
}


# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
    native <methods>;
}


-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}


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


# Preserve static fields of inner classes of R classes that might be accessed
# through introspection.
-keepclassmembers class **.R$* {
  public static <fields>;
}


# Preserve the special static methods that are required in all enumeration classes.
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}


-keep public class * {
    public protected *;
}


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

#實體類
-keep class com.bean.** { *; }
##---------------End: proguard configuration common for all Android apps ----------

#Gson
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
#避免混淆泛型
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
-keep class sun.misc.Unsafe.** { *; }
-keep class sun.misc.Unsafe.**
-keep class com.google.** { *; }

#org apache
-keep class org.apache.** { *; }
#baidumap
-keep class com.baidu.** { *; }
-keep class com.baidu.**
-keep class  vi.com.gdi.bgl.android.**{*;}
-keep class  vi.com.gdi.bgl.android.**
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
-dontwarn com.baidu.**
#chartengine
-keep class org.achartengine.** { *; }
-keep class org.achartengine.**
#youmeng
-keep class com.umeng.analytics.**{*;}
-keep class com.umeng.analytics.**
-keep class u.aly.** {*;}
-keep class u.aly.**
#alipay
-keep class com.alipay.** { *; }
-keep class com.alipay.**
-keep class com.ta.utdid2.** { *; }
-keep class com.ta.utdid2.**
-keep class com.ut.device.** { *; }
-keep class com.ut.device.**
-keep class org.json.alipay.** { *; }
-keep class org.json.alipay.**
#pinyin4j
-keep class com.hp.hpl.sparta..** { *; }
-keep class com.hp.hpl.sparta..**
-keep class demo..** { *; }
-keep class demo..**
-keep class net.sourceforge.pinyin4j..** { *; }
-keep class net.sourceforge.pinyin4j..**
#http legacy
#webkit
-keepclassmembers class * extends android.webkit.WebChromeClient{
    public void openFileChooser(...);
}
#open-sdk mta-sdk libammsdk
-keep class com.tencent..** { *; }
-keep class com.tencent..**
#zxing
-keep class com.google.zxing.** { *; }
-keep class com.google.zxing.**

-dontwarn java.lang.invoke**
-dontwarn org.apache.lang.**
-dontwarn org.apache.commons.**
-dontwarn com.com.nostra13.**
-dontwarn com.github.**
-dontwarn com.squareup.**

#retrofit
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
-keep class com.life.me.entity.postentity{*;}
-keep class com.life.me.entity.resultentity{*;}
-dontwarn retrofit.
-keep class retrofit. { *; }
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }

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

#阿里百川hotfix
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
    native <methods>;
}
-keep class com.alipay.euler.andfix.**{
    *;
}
-keep class com.taobao.hotfix.aidl.**{*;}
-keep class com.ta.utdid2.device.**{*;}
-keep class com.taobao.hotfix.HotFixManager{
    public *;
}
#如果是打修復包,需要在當前模組中放有對應版本的mapping.txt檔案
#再新增下面一行配置,保證修復前後兩個APK的混淆結果一致
-applymapping mapping.txt

#rx
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
 long producerIndex;
 long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
 rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
 rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

#okhttp
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**

#極光推送
-dontoptimize
-dontpreverify

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }

-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
#LitePal
-keep class org.litepal.** {
    *;
}
-keep class * extends org.litepal.crud.DataSupport {
    *;
}

#掃碼
-keepclassmembers class net.sourceforge.zbar.ImageScanner { *; }
-keepclassmembers class net.sourceforge.zbar.Image { *; }
-keepclassmembers class net.sourceforge.zbar.Symbol { *; }
-keepclassmembers class net.sourceforge.zbar.SymbolSet { *; }

#聯迪pos
-dontwarn com.landicorp.**

#新大陸pos
-dontwarn com.newland.**
-keep class com.newland.payment.trans.bean.** { *; }

#畫板
-dontwarn  me.panavtec.drawableview.**

DexGuard

對於更高的安全需求,Proguard可能有些力不從心了。而DexGuard就能提供更安全的保護,關於它的資料可以點這裡