![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 開(kāi)發(fā)應(yīng)該掌握的 Proguard 技巧_第1頁(yè)](http://file4.renrendoc.com/view/c51932c6d78a0269e4564b7a4a01ec61/c51932c6d78a0269e4564b7a4a01ec611.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 開(kāi)發(fā)應(yīng)該掌握的 Proguard 技巧_第2頁(yè)](http://file4.renrendoc.com/view/c51932c6d78a0269e4564b7a4a01ec61/c51932c6d78a0269e4564b7a4a01ec612.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 開(kāi)發(fā)應(yīng)該掌握的 Proguard 技巧_第3頁(yè)](http://file4.renrendoc.com/view/c51932c6d78a0269e4564b7a4a01ec61/c51932c6d78a0269e4564b7a4a01ec613.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 開(kāi)發(fā)應(yīng)該掌握的 Proguard 技巧_第4頁(yè)](http://file4.renrendoc.com/view/c51932c6d78a0269e4564b7a4a01ec61/c51932c6d78a0269e4564b7a4a01ec614.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 開(kāi)發(fā)應(yīng)該掌握的 Proguard 技巧_第5頁(yè)](http://file4.renrendoc.com/view/c51932c6d78a0269e4564b7a4a01ec61/c51932c6d78a0269e4564b7a4a01ec615.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android開(kāi)發(fā)應(yīng)該掌握的Proguard技巧
Proguard被人們熟知的是它的混淆功能,根據(jù)Proguard幫助文檔的描述,Proguard可以對(duì)Javaclass文件進(jìn)行shrink,optimize,obfuscate和preveirfy。obfuscate(混淆)只是其中之一。簡(jiǎn)要的介紹下這四個(gè)功能:壓縮(Shrink):檢測(cè)和刪除沒(méi)有使用的類,字段,方法和特性優(yōu)化(Optimize)
:分析和優(yōu)化Java字節(jié)碼混淆(Obfuscate):使用簡(jiǎn)短的無(wú)意義的名稱,對(duì)類,字段和方法進(jìn)行重命名預(yù)檢(Preveirfy):用來(lái)對(duì)Javaclass進(jìn)行預(yù)驗(yàn)證(預(yù)驗(yàn)證主要是針對(duì)JME開(kāi)發(fā)來(lái)說(shuō)的,Android中沒(méi)有預(yù)驗(yàn)證過(guò)程,默認(rèn)是關(guān)閉)補(bǔ)充說(shuō)明:根據(jù)proguard-android-optimize.txt對(duì)optimize的描述,在Android中使用該功能是有潛在風(fēng)險(xiǎn)的,并不能保證在所有版本的Dalvik虛擬機(jī)上正常運(yùn)行,該選項(xiàng)默認(rèn)是關(guān)閉的,如果開(kāi)啟,請(qǐng)做好全面的測(cè)試。在Android項(xiàng)目中,我們?cè)谙鄳?yīng)module下的build.gradle文件中會(huì)看到
buildTypes
{
release
{
minifyEnabled
true
proguardFiles
getDefaultProguardFile('proguard-android.txt'),
''
}
}其中minifyEnabled為true是開(kāi)啟Proguard的功能,false是關(guān)閉。Prouguard的工作流程如下圖所示:https://upload-images.jianshu.io/upload_images/14847428-25e69fd0c943d848?imageMogr2/auto-orient/strip可以看出,Proguard工作流程是對(duì)輸入的jars經(jīng)過(guò)shrink->optimize->obfuscate->preveirfy依次處理,圖中l(wèi)ibraryjars是inputjars運(yùn)行所依賴的包,比如Java運(yùn)行時(shí)的rt.jar,Android運(yùn)行時(shí)android.jar,這些jars在上述處理過(guò)程中不會(huì)有任何改變,僅是作為輸入jars的依賴。大家可能會(huì)有一個(gè)疑問(wèn),Proguard是怎么知道哪些類,方法,成員變量等是無(wú)用的呢,這就要說(shuō)到EntryPoint(入口點(diǎn)),我們?cè)谂渲梦募?包括默認(rèn)的proguard-android.txt)中寫入的一系列-keep選項(xiàng),都會(huì)作為EntryPoint,Proguard把這些EntryPoints作為搜索的入口,進(jìn)行遞歸檢索,以此來(lái)確定哪些部分未使用到。類似于hotspot虛擬機(jī)對(duì)可回收對(duì)象的判定,從GCRoots出發(fā),進(jìn)行可達(dá)性的判斷,不可達(dá)的為可回收對(duì)象。EntryPoints非常重要,Proguard的壓縮,優(yōu)化,混淆功能是以EntryPoint作為依據(jù)的(預(yù)檢不需要以此為依據(jù))。在壓縮過(guò)程中,Proguard從EntryPoints出發(fā),遞歸檢索,刪除那些沒(méi)有使用到的類和類的成員,在接下來(lái)的優(yōu)化過(guò)程中,那些非EntryPoints的類和方法會(huì)被設(shè)置成private,static或final,沒(méi)有使用到的參數(shù)會(huì)被移除,有些方法可能會(huì)被標(biāo)記為內(nèi)聯(lián)的,在混淆過(guò)程中,會(huì)對(duì)非EntryPoint的類和類的成員進(jìn)行重命名,也就是用其它無(wú)意義的名稱代替。我們?cè)谂渲梦募杏?keep保留的部分屬于EntryPoint,所以不會(huì)被重命名。說(shuō)起重命名,為什么需要保留一些類和類的成員(方法和變量)不被重命名呢?原因是Proguard對(duì)class文件經(jīng)過(guò)一系列處理后,能保證功能上和原來(lái)是一樣的,但有些情況它卻不能良好的處理,比如我們代碼中有些功能依賴于它們?cè)瓉?lái)的名字,如反射功能,native調(diào)用(函數(shù)簽名)等,如果換成其它名字,會(huì)出現(xiàn)找不到,不對(duì)應(yīng)的情況,可能引起程序崩潰,或者我們的對(duì)外提供了一些功能,必須保持原來(lái)的名字,才能保證其它依賴這些功能的模塊能正確的運(yùn)行等。這就是我們?yōu)槭裁匆渲?keep選項(xiàng)的原因之一,還有一個(gè)原因是我們要用-keep告訴Proguard程序的入口(帶有-keep的選項(xiàng)都會(huì)作為EntryPoint),以此來(lái)確定哪些是未被使用的類和類的成員,方法等,并刪除它們,因此,我們要針對(duì)我們的項(xiàng)目配置對(duì)應(yīng)的選項(xiàng)。當(dāng)然Proguard不僅提供了-keep選項(xiàng),還有一些其它配置選項(xiàng),比如-dontoptimize對(duì)輸入的Javaclass文件不進(jìn)行優(yōu)化處理,-verbose生成混淆后的映射文件等。下面介紹一下app中proguard文件的常用配置和項(xiàng)目中可能會(huì)用到的指令。更多詳細(xì)的用法,可以參考Proguard幫助文檔。第1條是可以作為AndroidApp的配置模板的(默認(rèn)的proguard-android.txt文件里的配置沒(méi)有列舉出來(lái)),基本所有的app都會(huì)用到。通用配置#代碼混淆壓縮比,在0~7之間,默認(rèn)為5,一般不做修改
-optimizationpasses
5#把混淆類中的方法名也混淆了-useuniqueclassmembernames#優(yōu)化時(shí)允許訪問(wèn)并修改有修飾符的類和類的成員
-allowaccessmodification#
避免混淆內(nèi)部類、泛型、匿名類-keepattributes
InnerClasses,Signature,EnclosingMethod#拋出異常時(shí)保留代碼行號(hào)
-keepattributes
SourceFile,LineNumberTable#重命名拋出異常時(shí)的文件名稱為"SourceFile"-renamesourcefileattribute
SourceFile#保持所有實(shí)現(xiàn)
Serializable
接口的類成員-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();
}#保留我們使用的四大組件,自定義的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
#保留support下的所有類及其內(nèi)部類
-keep
class
android.support.**
{*;}#
保留繼承的support類-keep
public
class
*
extends
android.support.v4.**
-keep
public
class
*
extends
android.support.v7.**
-keep
public
class
*
extends
android.support.annotation.**
#保留我們自定義控件(繼承自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);
}#Fragment不需要在AndroidManifest.xml中注冊(cè),需要額外保護(hù)下-keep
public
class
*
extends
android.app.Fragment#
保持測(cè)試相關(guān)的代碼
-dontnote
junit.framework.**
-dontnote
junit.runner.**
-dontwarn
android.test.**
-dontwarn
android.support.test.**
-dontwarn
org.junit.**下面是針對(duì)我們App的配置。1.實(shí)體類需要保留我們需要保留實(shí)體類的get和set方法(反射會(huì)用到),boolean類型的get方法是isXXX,不要忘記保留。
-keep
public
class
com.dev.example.entity.**
{
public
void
set*(***);
public
***
get*();
public
***
is*();
}如果所有的實(shí)體類在一個(gè)包下的話,上面的配置只用寫一遍就可以了??墒菍?shí)際中我們更多的是以業(yè)務(wù)來(lái)劃分包名的,于是我們還可以這樣配置(實(shí)體類的類名一定要含有"Model")<pre>-keep
public
class
**.*Model*.**
{
public
void
set*(***);
public
***
get*();
public
***
is*();
}2.對(duì)內(nèi)部類的處理如果項(xiàng)目中使用了內(nèi)部類,要對(duì)其進(jìn)行保留。保留寫在某個(gè)類里面的所有內(nèi)部類。下面表示寫在類A里面的內(nèi)部類都會(huì)被保留($符號(hào)是用來(lái)分割內(nèi)部類與其母體的標(biāo)志),什么意思呢,比如類A里面有一個(gè)內(nèi)部類B,而B(niǎo)里面也有個(gè)內(nèi)部類C,這時(shí),B和C都會(huì)被保留,以此類推,對(duì)多重嵌套的情況,都會(huì)被保留(當(dāng)然我們寫代碼也不會(huì)寫出這么深層級(jí)的內(nèi)部類出來(lái)),這里的內(nèi)部類包含靜態(tài)內(nèi)部類,非靜態(tài)內(nèi)部類,不包含匿名內(nèi)部類,如果是匿名內(nèi)部類,只會(huì)保留其方法和成員變量(其繼承的類或?qū)崿F(xiàn)的接口的名字會(huì)被混淆),另外如果對(duì)應(yīng)的類被保留,在該類里面定義的接口也會(huì)被保留,{*;}匹配該類里面的所有部分。-keep
class
com.dev.example.A$*
{
*;
}保留寫在某個(gè)內(nèi)部類里面所有的內(nèi)部類。這話聽(tīng)著有點(diǎn)繞口,舉個(gè)例子,類A里面有個(gè)內(nèi)部類B,下面表示寫在類B里面的內(nèi)部類都會(huì)被保留。此時(shí),類B像上面第一點(diǎn)所舉得類A一樣,有點(diǎn)遞歸意思在里面。還有就是此時(shí)類B的名字不會(huì)被混淆,但里面的方法和成員變量會(huì)被混淆,如果其它地方?jīng)]有對(duì)類B的方法和成員變量進(jìn)行保留的話。-keep
class
com.dev.example.A$B$*
{
*;
}3.對(duì)webView進(jìn)行處理
-keepclassmembers
class
erface.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);
}4.保留js調(diào)用的原生方法如果我們的app中涉及到和h6交互,需要保留js調(diào)用的原生方法。#
Keep
JavascriptInterface-keepclassmembers
class
**
{
@android.webkit.JavascriptInterface
public
*;
}5.對(duì)含有反射類的處理有時(shí)候項(xiàng)目中有些類不是實(shí)體類,但仍然用到反射功能,如Class.forName("xxx"),這是我們需要保留的。比如這些類在com.dev.example包下,可以通過(guò)下面的配置進(jìn)行保留。-keep
class
com.dev.example.*
{
*;
}另外上面只是保留了該包下的類,如果該包下還有子包,則子包的類仍然會(huì)被混淆,如果想保留該包下子包的類,我們可以如下配置(**能匹配本包和所含子包,其中子包也可以含有子包)-keep
class
com.dev.example.**{
*;
}6.常見(jiàn)的自定義的配置1.保留某個(gè)特定的類#保留Test類-keep
public
class
com.dev.example.Test
{
*;
}2.保留某個(gè)類的子類#保留繼承了AbstractClass的子類-keep
class
*
extends
com.dev.example.AbstractClass{*;}3.保留接口的實(shí)現(xiàn)類#保留實(shí)現(xiàn)了Callable接口的類-keep
class
*
implements
Callable{*;}4.保留類的特定部分保留TaskRepository類的所有構(gòu)造方法,變量和普通方法。-keep
class
com.dev.example.TaskRepository{
<init>;
//匹配所有構(gòu)造器
<fields>;
//匹配所有域
<methods>;
//匹配所有方法}還可以保留的更具體一點(diǎn),如下所示-keepclassmembers
com.dev.example.TaskRepository{
//
保留該類的修飾符是public且有一個(gè)參數(shù)(類型是String)的構(gòu)造方法
public
<init>(java.lang.String);
//
保留該類的所有修飾符是public且返回類型void的方法
public
void
*(**);
//
保留該類的具體某一個(gè)方法
public
String
getUserName();
}7.對(duì)于第三方依賴庫(kù)的處理下面給出幾個(gè)例子,用到具體第三發(fā)依賴庫(kù)的時(shí)候,對(duì)應(yīng)的文檔會(huì)給出相應(yīng)配置的。#okhttp-dontwarn
com.squareup.okhttp.**
-dontwarn
com.squareup.okhttp3.**
-keep
class
com.squareup.okhttp3.**
{
*;}
-dontwarn
okio.**#retroift-dontwarn
retrofit2.**
-keep
class
retrofit2.**
{
*;
}
-keepattributes
Signature
-keepattributes
Exceptions#
fresco
SDK-keep,allowobfuscation
@interface
ernal.DoNotStrip#
Do
not
strip
any
method/class
that
is
annotated
with
@DoNotStrip-keep
@ernal.DoNotStrip
class
*-keepclassmembers
class
*
{
@ernal.DoNotStrip
*;
}#rx-dontwarn
rx.**
-keep
class
rx.**
{
*;}#keep
GSON
stuff-keep
class
sun.misc.Unsafe
{
*;
}
-keep
class
com.google.gson.**
{
*;
}#ButterKnife-keep
class
butterknife.**
{
*;
}
-dontwarn
ernal.**
-keep
class
**$ViewBinder
{
*;
}
-keepclasseswithmembernames
class
*
{
@butterknife.*
<fields>;
}
-keepclasseswithmembernames
class
*
{
@butterknife.*
<methods>;
}#enventbus-keep
class
org.greenrobot.eventbus.**
{
*;}
-dontwarn
org.greenrobot.eventbus.**
-keepclassmembers
class
**
{另外說(shuō)一下
public
void
onEvent*(**);
}#
Bugly-dontwarn
com.tencent.bugly.**
-keep
public
class
com.tencent.bugly.**{*;}#
aliyun
push-keepclasseswithmembernames
class
**
{
native
<methods>;
}#
share
SDK-dontwarn
com.tencent.**
-keepnames
class
com.tencent.**
{*;}#
sina
share
SDK-dontwarn
com.sina.**
-keepnames
class
com.sina.**
{*;}#
umeng
SDK-keep
public
class
*
extends
com.umeng.**-dontwarn
com.umeng.**
-keep
class
com.umeng.**
{
*;
}其它還有關(guān)于多module項(xiàng)目的配置,一種方法是關(guān)閉子module的Proguard功能,在我們主app的文件中配置所有module的配置選項(xiàng)。這樣會(huì)使主app的proguard配置文件變得比較雜亂,如果業(yè)務(wù)發(fā)展過(guò)程中,某個(gè)子module的功能不需要了,還要在主app的配置文件中找到對(duì)應(yīng)子module的配置,并刪除它們,不建議使用。另一種方式是各個(gè)module配置好自己的配置文件,要注意的是,子module中制定配置文件的方式如下所示:buildTypes
{
release
{
consumerProguardFiles
''
}
}子module是通過(guò)consumerProguardFiles來(lái)指定配置文件的,而不是proguardFiles。在導(dǎo)出包時(shí),如果發(fā)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 華師大版數(shù)學(xué)七年級(jí)上冊(cè)《2.13 有理數(shù)的混合運(yùn)算》聽(tīng)評(píng)課記錄2
- 《兩漢的科技和文化》名師聽(tīng)課評(píng)課記錄(新部編人教版七年級(jí)上冊(cè)歷史)
- 陜教版道德與法治九年級(jí)下冊(cè)9.2《做負(fù)責(zé)公民》聽(tīng)課評(píng)課記錄
- 現(xiàn)場(chǎng)安全方案協(xié)議書(2篇)
- 人教部編版八年級(jí)下冊(cè)道德與法治1.2《治國(guó)安邦的總章程》 聽(tīng)課評(píng)課記錄
- 小學(xué)數(shù)學(xué)-五年級(jí)下冊(cè)-1-1觀察物體(聽(tīng)評(píng)課記錄)
- 部編版八年級(jí)歷史上冊(cè)《第17課 中國(guó)工農(nóng)紅軍長(zhǎng)征》表格式聽(tīng)課評(píng)課記錄
- 中圖版歷史七年級(jí)下冊(cè)第12課《影響世界的宋元科技成就》聽(tīng)課評(píng)課記錄
- 魯教版歷史六年級(jí)上冊(cè)第8課《大變革的時(shí)代》聽(tīng)課評(píng)課記錄
- 五年級(jí)上冊(cè)數(shù)學(xué)聽(tīng)評(píng)課記錄《5.5 分?jǐn)?shù)基本性質(zhì)》(4)-北師大版
- 工業(yè)機(jī)器人編程語(yǔ)言:Epson RC+ 基本指令集教程
- 2024年同等學(xué)力申碩統(tǒng)考英語(yǔ)卷
- 2023.05.06-廣東省建筑施工安全生產(chǎn)隱患識(shí)別圖集(高處作業(yè)吊籃工程部分)
- 2023年漢中市人民政府國(guó)有資產(chǎn)監(jiān)督管理委員會(huì)公務(wù)員考試《行政職業(yè)能力測(cè)驗(yàn)》歷年真題及詳解
- 2024年上海高考數(shù)學(xué)真題試題(原卷版+含解析)
- JTG 3362-2018公路鋼筋混凝土及預(yù)應(yīng)力混凝土橋涵設(shè)計(jì)規(guī)范
- 八年級(jí)下冊(cè)歷史思維導(dǎo)圖
- 電動(dòng)汽車用驅(qū)動(dòng)電機(jī)系統(tǒng)-編制說(shuō)明
- 江蘇卷2024年高三3月份模擬考試化學(xué)試題含解析
- 2024年四川省成都市新都區(qū)中考英語(yǔ)一診試卷(含解析)
- 醫(yī)療器械物價(jià)收費(fèi)申請(qǐng)流程
評(píng)論
0/150
提交評(píng)論