一浦马、配置( 項(xiàng)目的app/build.gradle)
buildTypes {
release {
/*打開(kāi)混淆*/
minifyEnabled true
/*打開(kāi)資源壓縮*/
shrinkResources true
zipAlignEnabled true // Zipalign優(yōu)化
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
proguard-android.txt
是官方提供的通用混淆配置够颠,文件路徑在 \sdk\tools\proguard\proguard-android.txt
下
proguard-rules.pro
即自定義配置文件
proguardFiles getDefaultProguardFile('proguard-android.txt'),
file('proguard-rules.pro'),
project.ext.LiteDir + 'buildOperation/proguard.cfg',
file('../PluginSDK/proguard-rules.pro'),
file('../LibThemeEngine/proguard-rules.pro'),
二、混淆為什么要保留類名或方法名罐栈?
- 1抛蚤、讓C/C++程序可以通過(guò)jni使用對(duì)應(yīng)的java方法
- 2若锁、四大組件由于在AndroidManifest.xml里面注冊(cè)了,所以需要保留什荣。
- 3、R文件混淆會(huì)導(dǎo)致引用錯(cuò)誤怀酷。
- 4稻爬、第三方架包有的已經(jīng)經(jīng)過(guò)混淆了,再次混淆會(huì)導(dǎo)致找不到類名或者方法名
三蜕依、什么時(shí)候不被混淆桅锄?
一般以下情況都會(huì)不混淆:
- 1、使用了
自定義控件
那么要保證它們不參與混淆 - 2样眠、使用了
枚舉
要保證枚舉不被混淆 - 3友瘤、對(duì)
第三方庫(kù)
中的類不進(jìn)行混淆 - 4、運(yùn)用了
反射的類
也不進(jìn)行混淆 - 5檐束、使用了 Gson 之類的工具要使
JavaBean
類即實(shí)體類不被混淆 - 6辫秧、
靜態(tài)成員
、JNI中調(diào)用的類
- 7被丧、有用到
WebView
的JS 調(diào)用
也需要保證寫(xiě)的接口方法
不混淆盟戏,原因和第一條一樣 - 8、
Serializable
,Parcelable
的子類和Creator
靜態(tài)成員變量不混淆晚碾,否則會(huì)產(chǎn)生 Android.os.BadParcelableException 異常 - 9抓半、
四大組件
,自定義的Application
四格嘁、混淆語(yǔ)法
- 2.1 基本規(guī)則
兩個(gè)常用的混淆命令笛求,注意一顆星表示只是保持該包下的類名,而子包下的類名還是會(huì)被混淆糕簿;而兩顆星表示把本包和所包含的子包下的類名都保留探入。
-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*
如果既想保持類名,又想保持里面的內(nèi)容不被混淆懂诗,就執(zhí)行以下方法
-keep class com.example.bean.** { *; }
在此基礎(chǔ)上蜂嗽,我們也可以使用Java的基本規(guī)則來(lái)保護(hù)特定類不被混淆,比如我們可以用extend殃恒,implement等這些Java規(guī)則植旧。如下例子就避免所有繼承Activity的類被混淆
保留我們使用的四大組件辱揭,自定義的Application等等這些類不被混淆
因?yàn)檫@些子類都有可能被外部調(diào)用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
- 2.2、基本混淆模板
對(duì)于一些基本指令的添加
#############################################
#
# 對(duì)于一些基本指令的添加
#
#############################################
#保證使用同一套 mapping 文件病附,從而保證前后打包一直问窃。
#mapping文件時(shí)混淆前后文件的映射關(guān)系
-applymapping mapping.txt
# 代碼混淆壓縮比,在0~7之間完沪,默認(rèn)為5域庇,一般不做修改
-optimizationpasses 5
# 混合時(shí)不使用大小寫(xiě)混合,混合后的類名為小寫(xiě)
-dontusemixedcaseclassnames
# 指定不去忽略非公共庫(kù)的類
-dontskipnonpubliclibraryclasses
# 這句話能夠使我們的項(xiàng)目混淆后產(chǎn)生映射文件# 包含有類名->混淆后類名的映射關(guān)系
-verbose
# 指定不去忽略非公共庫(kù)的類成員
-dontskipnonpubliclibraryclassmembers
# 不做預(yù)校驗(yàn)覆积,preverify是proguard的四個(gè)步驟之一听皿,Android不需要preverify扒寄,去掉這一步能夠加快混淆速度腺律。
-dontpreverify
# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature
#將文件來(lái)源重命名為“SourceFile”字符串
-renamesourcefileattribute SourceFile
# 拋出異常時(shí)保留代碼行號(hào)
-keepattributes SourceFile,LineNumberTable
# 避免混淆Annotation猩谊、內(nèi)部類专酗、泛型公条、匿名類
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod
# 指定混淆是采用的算法催首,后面的參數(shù)是一個(gè)過(guò)濾器# 這個(gè)過(guò)濾器是谷歌推薦的算法隅茎,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*
#把混淆類中的方法名也混淆了
-useuniqueclassmembernames
#優(yōu)化時(shí)允許訪問(wèn)并修改有修飾符的類和類的成員
-allowaccessmodification
Android開(kāi)發(fā)中一些需要保留的公共部分
#############################################
#
# Android開(kāi)發(fā)中一些需要保留的公共部分
#
#############################################
# 保留我們使用的四大組件广恢,自定義的Application等等這些類不被混淆# 因?yàn)檫@些子類都有可能被外部調(diào)用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
# 保留support下的所有類及其內(nèi)部類
-keep class android.support.** {*;}
# 保留繼承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
# 保留R下面的資源
-keep class **.R$* {*;}
# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保留在Activity中的方法參數(shù)是view的方法欣孤,
# 這樣以來(lái)我們?cè)趌ayout中寫(xiě)的onClick就不會(huì)被影響
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}
# 保留枚舉類不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留我們自定義控件(繼承自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);
}
# 保留Parcelable序列化類不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# 保留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();
}
# 對(duì)于帶有回調(diào)函數(shù)的onXXEvent馋没、**On*Listener的,不能被混淆
-keepclassmembers class * {
void *(**On*Event);
void *(**On*Listener);
}
# webView處理降传,項(xiàng)目中沒(méi)有使用到webView忽略即可
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-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.webViewClient {
public void *(android.webkit.webView, jav.lang.String);
}
# assume no side effects:刪除android.util.Log輸出的日志
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
public static *** w(...);
public static *** e(...);
}
#保留Keep注解的類名和方法
-keep,allowobfuscation @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclassmembers class * {
@android.support.annotation.Keep *;
}
#fastjson混淆
-keepattributes Signature
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.**{*;}
-keep class com.alibaba.fastjson.**{*; }
-keep public class com.ninstarscf.ld.model.entity.**{*;}
# 保持測(cè)試相關(guān)的代碼
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.*
# webview
-keep class android.webkit.JavascriptInterface {*;}
#自定義webview接口實(shí)現(xiàn)類
-keep public class com.gjmetal.app.ui.ball.**{*;}
# 微信支付
-dontwarn com.tencent.mm.**
-dontwarn com.tencent.wxop.stat.**
-keep class com.tencent.mm.** {*;}
-keep class com.tencent.wxop.stat.**{*;}
# 支付寶錢(qián)包
-dontwarn com.alipay.**
-dontwarn HttpUtils.HttpFetcher
-dontwarn com.ta.utdid2.**
-dontwarn com.ut.device.**
-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 *;}
-keep class com.alipay.mobilesecuritysdk.*
-keep class com.ut.*
五篷朵、其他混淆
然后需要在項(xiàng)目生成的混淆腳本中添加過(guò)濾混淆的條件
# Glide
-dontwarn com.bumptech.glide.**
-keep class com.bumptech.glide.**{*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# Gson
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# OkHttp3
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# Okio
-dontwarn com.squareup.**
-dontwarn okio.**
-keep public class org.codehaus.* { *; }
-keep public class java.nio.* { *; }
# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
# RxJava RxAndroid
-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;
}
#數(shù)據(jù)模型(實(shí)體類)
-keep class com.seekfangle.pad.bean.* {*;}
#第三方架包
-keep class cn.com.** { *;}
-keep class android_serialport_api.** { *;}
#butterknife
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
#EventBus3.0
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
#友盟
-keep class com.umeng.** {*;}
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public class com.gjmetal.app.R$*{
public static final int *;
}
#個(gè)推
-dontwarn com.igexin.**
-keep class com.igexin.** { *; }
-keep class org.json.** { *; }
-keep class android.support.v4.app.NotificationCompat { *; }
-keep class android.support.v4.app.NotificationCompat$Builder { *; }
#routes
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
#ShareSdk
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class **.R$* {*;}
-keep class **.R{*;}
-keep class com.mob.**{*;}
-keep class m.framework.**{*;}
-dontwarn cn.sharesdk.**
-dontwarn com.sina.**
-dontwarn com.mob.**
-dontwarn **.R$*
#Picasso
-keep class com.parse.*{ *; }
-dontwarn com.parse.**
-dontwarn com.squareup.picasso.**
-keepclasseswithmembernames class * {
native <methods>;
}
#GreenDao
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use Rx:
-dontwarn rx.**
#百度定位混淆配置
-keep class vi.com.gdi.** { *; }
-keep public class com.baidu.** {*;}
-keep public class com.mobclick.** {*;}
-dontwarn com.baidu.mapapi.utils.*
-dontwarn com.baidu.platform.comapi.b.*
-dontwarn com.baidu.platform.comapi.map.*
#百度地圖混淆配置
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
-dontwarn com.baidu.**
-keep class mapsdkvi.com.** {*;}
#QQ分享
-dontwarn com.tencent.**
-keep class com.tencent.** {*; }
#微信分享
-keep class com.tencent.mm.opensdk.** {*;}
-keep class com.tencent.wxop.** {*;}
-keep class com.tencent.mm.sdk.** { *;}
六、檢查混淆結(jié)果
混淆過(guò)的包必須進(jìn)行檢查婆排,避免因混淆引入的bug声旺。
一方面,需要從代碼層面檢查段只。使用上文的配置進(jìn)行混淆打包后在<module-name>/build/outputs/mapping/release/
目錄下會(huì)輸出以下文件:
dump.txt
描述APK文件中所有類的內(nèi)部結(jié)構(gòu)
mapping.txt
提供混淆前后類腮猖、方法、類成員等的對(duì)照表
seeds.txt
列出沒(méi)有被混淆的類和成員
usage.txt
列出被移除的代碼
我們可以根據(jù)seeds.txt
文件檢查未被混淆的類和成員中是否已包含所有期望保留的赞枕,再根據(jù)usage.txt
文件查看是否有被誤移除的代碼澈缺。
另一方面,需要從測(cè)試方面檢查炕婶。將混淆過(guò)的包進(jìn)行全方面測(cè)試姐赡,檢查是否有 bug 產(chǎn)生。
七柠掂、解出混淆棧
混淆后的類项滑、方法名等等難以閱讀,這固然會(huì)增加逆向工程的難度涯贞,但對(duì)追蹤線上 crash 也造成了阻礙枪狂。我們拿到 crash 的堆棧信息后會(huì)發(fā)現(xiàn)很難定位危喉,這時(shí)需要將混淆反解。
在<sdk-root>/tools/proguard/
路徑下有附帶的的反解工具(Window 系統(tǒng)為proguardgui.bat摘完,Mac 或 Linux 系統(tǒng)為proguardgui.sh
)姥饰。
這里以 Window 平臺(tái)為例。雙擊運(yùn)行proguardgui.ba
t 后孝治,可以看到左側(cè)的一行菜單。點(diǎn)擊 ReTrace审磁,選擇該混淆包對(duì)應(yīng)的 mapping 文件(混淆后在<module-name>/build/outputs/mapping/release/
路徑下會(huì)生成mapping.txt
文件谈飒,它的作用是提供混淆前后類、方法态蒂、類成員等的對(duì)照表)杭措,再將 crash 的 stack trace 黏貼進(jìn)輸入框中,點(diǎn)擊右下角的 ReTrace 钾恢,混淆后的堆棧信息就顯示出來(lái)了手素。
以上使用 GUI 程序進(jìn)行操作,另一種方式是利用該路徑下的 retrace 工具通過(guò)命令行進(jìn)行反解瘩蚪,命令是
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
例如:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
注意事項(xiàng):
所有在 AndroidManifest.xml
涉及到的類已經(jīng)自動(dòng)被保持泉懦,因此不用特意去添加這塊混淆規(guī)則。(很多老的混淆文件里會(huì)加疹瘦,現(xiàn)在已經(jīng)沒(méi)必要)
proguard-android.txt
已經(jīng)存在一些默認(rèn)混淆規(guī)則崩哩,沒(méi)必要在proguard-rules.pro
重復(fù)添加
mapping.txt
中的混淆前后的類對(duì)照如下:
//混淆前的文件 -> 混淆后的文件
org.aspectj.runtime.reflect.SourceLocationImpl -> c.a.b.b.g:
java.lang.String fileName -> a
int line -> b
24:28:void <init>(java.lang.Class,java.lang.String,int) -> <init>
31:31:java.lang.String getFileName() -> a
32:32:int getLine() -> b
36:36:java.lang.String toString() -> toString
org.aspectj.runtime.reflect.StringMaker -> c.a.b.b.h:
org.aspectj.runtime.reflect.StringMaker middleStringMaker -> g
org.aspectj.runtime.reflect.StringMaker longStringMaker -> h
org.aspectj.runtime.reflect.StringMaker shortStringMaker -> f
int cacheOffset -> e
boolean shortTypeNames -> a
boolean includeArgs -> b
boolean includeModifiers -> c
boolean shortPrimaryTypeNames -> d
33:69:void <clinit>() -> <clinit>
19:28:void <init>() -> <init>
八、自定義混淆規(guī)則
在上文“混淆配置”中有這樣一行代碼
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
這行代碼定義了混淆規(guī)則由兩部分構(gòu)成:位于 SDK 的tools/proguard/
文件夾中的 proguard-android.txt
的內(nèi)容以及默認(rèn)放置于模塊根目錄的proguard-rules.pro
的內(nèi)容言沐。前者是 SDK 提供的默認(rèn)混淆文件邓嘹,后者是開(kāi)發(fā)者自定義混淆規(guī)則的地方。
九险胰、常見(jiàn)的混淆指令
- 1汹押、
optimizationpasses
代碼混淆壓縮比,在0~7之間起便,默認(rèn)為5棚贾,一般不做修改 - 2、
dontoptimize
不進(jìn)行優(yōu)化 - 3缨睡、
dontusemixedcaseclassnames
混合時(shí)不使用大小寫(xiě)混合鸟悴,混合后的類名為小寫(xiě) - 4、
dontskipnonpubliclibraryclasses
指定不去忽略非公共庫(kù)的類 - 5奖年、
dontpreverify
不做預(yù)校驗(yàn) - 6细诸、
dontwarn
不提示警告,和keep可以說(shuō)是形影不離,尤其是處理引入的library時(shí). - 7陋守、
verbose
混淆時(shí)是否記錄日志 - 8震贵、
optimizations
指定混淆是采用的算法利赋,后面的參數(shù)是一個(gè)過(guò)濾器 - 9、
keep
保留類和類中的成員猩系,防止被混淆或移除 - 10媚送、
keepnames
保留類和類中的成員,防止被混淆寇甸,成員沒(méi)有被引用會(huì)被移除 - 11塘偎、
keepclassmembers
只保留類中的成員,防止被混淆或移除 - 12拿霉、
keepclassmembernames
只保留類中的成員吟秩,防止被混淆,成員沒(méi)有引用會(huì)被移除 - 13绽淘、
keepclasseswithmembers
保留類和類中的成員涵防,防止被混淆或移除,保留指明的成員 - 14沪铭、
keepclasseswithmembernames
保留類和類中的成員壮池,防止被混淆,保留指明的成員杀怠,成員沒(méi)有引用會(huì)被移除 - 15椰憋、
dontshrink
不壓縮類文件。默認(rèn)情況下會(huì)壓縮所有的類文件驮肉,除了那些用keep聲明和被這些類依賴的class
更多詳細(xì)的請(qǐng)到官網(wǎng)
十熏矿、規(guī)則
[保持命令] [類] {
[成員]
}
“類”代表類相關(guān)的限定條件,它將最終定位到某些符合該限定條件的類离钝。它的內(nèi)容可以使用:
- 具體的類
- 訪問(wèn)修飾符
public票编、protected、private
- 通配符
*
卵渴,匹配任意長(zhǎng)度字符慧域,但不含包名分隔符(.)- 通配符
**
,匹配任意長(zhǎng)度字符浪读,并且包含包名分隔符(.)extends
昔榴,即可以指定類的基類
*implement
,匹配實(shí)現(xiàn)了某接口的類$
碘橘,內(nèi)部類
成員
代表類成員相關(guān)的限定條件互订,它將最終定位到某些符合該限定條件的類成員。它的內(nèi)容可以使用:
<init>
匹配所有構(gòu)造器<fields>
匹配類中的所有字段<methods>
匹配所有方法- 通配符
*
痘拆,匹配任意長(zhǎng)度字符仰禽,但不含包名分隔符(.)- 通配符
**
,匹配任意長(zhǎng)度字符,并且包含包名分隔符(.)- 通配符
***
吐葵,匹配任意參數(shù)類型…
规揪,匹配任意長(zhǎng)度的任意類型參數(shù)。比如void test(…)
就能匹配任意void test(String a)
或者是void test(int a, String b)
這些方法温峭。- 訪問(wèn)修飾符
public猛铅、protected、private
指定成員
\ 代表任意構(gòu)造方法.
\ 代表任意域.
\ 代表任意方法.
* 代表任意成員(包括成員變量和方法).
類型描述通配符
% 表示任意基本類型(int,char等,但是不包括void).
? 表示類名中的任意單個(gè)字符.
* 表示類名中的任意多個(gè)字符,不包括分隔符(.).
** 表示類名中的任意多個(gè)字符,包括分隔符(.).
*** 表示任意類型.
... 表示任意多個(gè)任意類型的參數(shù).
舉個(gè)例子凤藏,假如需要將com.biaobiao.test包下所有繼承Activity的public類及其構(gòu)造函數(shù)都保持住奸忽,可以這樣寫(xiě):
-keep public class com.biaobiao.test.** extends Android.app.Activity {
<init>
}
十一、常用自定義混淆規(guī)則
1揖庄、不混淆某個(gè)類
-keep public class com.biaobiao.example.Test { *; }
2月杉、不混淆某個(gè)包所有的類
-keep class com.biaobiao.test.** { *; }
3、不混淆某個(gè)類的子類
-keep public class * extends com.biaobiao.example.Test { *; }
4抠艾、不混淆某個(gè)接口的實(shí)現(xiàn)
-keep class * implements com.biaobiao.example.TestInterface { *; }
5、不混淆某個(gè)類的構(gòu)造方法
-keepclassmembers class com.biaobiao.example.Test {
public <init>();
}
//保持指定類的所有字段
-keep class com.xy.myapp.MyClass { public <fields>; }
6桨昙、不混淆某個(gè)類的特定的方法
-keepclassmembers class com.biaobiao.example.Test {
public void test(java.lang.String);
}
//保持指定類的所有方法
-keep class com.xy.myapp.MyClass { public <methods>; }
//保持用指定參數(shù)作為形參的方法
-keep class com.xy.myapp.MyClass { public <methods>(java.lang.String); }
7检号、不混淆某個(gè)類的內(nèi)部類
//所有內(nèi)部類
-keep class com.biaobiao.example.Test$* { *; }
//內(nèi)部類 Builder
-keep class com.biaobiao.example.Test$Builder { *; }
//保持MyClass內(nèi)部類JavaScriptInterface中的所有public內(nèi)容。
-keepclassmembers class com.xy.myapp.MyClass$JavaScriptInterface {
#保持該類下所有的共有內(nèi)容不被混淆
public *;
#保持該類下所有的私有方法不被混淆
private * ;
}
8蛙酪、混淆引入的 library
//使指定的類不輸出警告信息
-dontwarn purang.purang_shop.**
-keep class purang.purang_shop.**{*;}
十二齐苛、組件模塊定義混淆規(guī)則
子模塊混淆文件的指定是通過(guò)consumerProguardFiles
這個(gè)屬性來(lái)指定的,并不是proguardFiles
屬性桂塞,而且我們無(wú)需配置其他的選項(xiàng)凹蜂,只需要配置consumerProguardFiles
屬性就可以。該屬性表示在打包的時(shí)候會(huì)自動(dòng)尋找該module下我們指定的混淆文件對(duì)代碼進(jìn)行混淆阁危。可以把一些公共的混淆定義在子模塊中玛痊。
release {
consumerProguardFiles 'proguard-rules.pro'
}
consumerProguardFiles作用:
- proguard.txt會(huì)被打包進(jìn)aar中
- 此配置只對(duì)aar進(jìn)行混淆。
- 此配置只對(duì)庫(kù)文件有效狂打,對(duì)應(yīng)用程序無(wú)效擂煞。
當(dāng)app模塊將全部代碼匯總混淆時(shí),Library
模塊會(huì)被打包為release aar
趴乡,然后被引用匯總对省,通過(guò)proguard-rule.pro
規(guī)則各自混淆,保證只混淆一次晾捏。
組件化工程中具體混淆用法:
我們可以將固定的第三方混淆放到base模塊的proguard-rule.pro文件中蒿涎,每個(gè)模塊獨(dú)有的第三方引用庫(kù)混淆放到各自的proguard-rule.pro文件中,在app模塊的proguard-rule.pro文件中放入Android基礎(chǔ)屬性的混淆聲明惦辛,如四大組件和全局的混淆等配置劳秋。這樣可以最大限度的完成混淆解耦操作。
十三、自定義要保持的資源
資源壓縮包含了“合并資源”和“移除資源”兩個(gè)流程俗批∷谆颍“合并資源”流程中,名稱相同的資源被視為重復(fù)資源會(huì)被合并岁忘。需要注意的是辛慰,這一流程不受shrinkResources
屬性控制,也無(wú)法被禁止干像, gradle 必然會(huì)做這項(xiàng)工作帅腌。
當(dāng)我們開(kāi)啟了資源壓縮之后,系統(tǒng)會(huì)默認(rèn)替我們移除所有未使用的資源麻汰,假如我們需要保留某些特定的資源速客,可以在我們項(xiàng)目中創(chuàng)建一個(gè)被 <resources> 標(biāo)記的 XML 文件(如 res/raw/keep.xml)
,并在tools:keep
屬性中指定每個(gè)要保留的資源五鲫,在tools:discard
屬性中指定每個(gè)要舍棄的資源溺职。這兩個(gè)屬性都接受逗號(hào)分隔的資源名稱列表。同樣位喂,我們可以使用字符 * 作為通配符浪耘。
<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/activity_video*,@layout/dialog_update_v2"
tools:discard="@layout/unused_layout,@drawable/unused_selector" />
十四、移除替代資源
一些替代資源塑崖,例如多語(yǔ)言支持的 strings.xml七冲,多分辨率支持的 layout.xml 等,在我們不需要使用又不想刪除掉時(shí)规婆,可以使用資源壓縮將它們移除澜躺。我們使用 resConfig 屬性來(lái)指定需要支持的屬性,例如
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}