Android 混淆 (不定期完善第三方混淆規則)
阿新 • • 發佈:2019-01-31
開啟混淆
在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就能提供更安全的保護,關於它的資料可以點這裡