Android代碼混淆

Android知識(shí)總結(jié)

一浦马、配置( 項(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被丧、有用到 WebViewJS 調(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.bat 后孝治,可以看到左側(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ù)添加

混淆的文件對(duì)照表

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"
      }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抒蚜,一起剝皮案震驚了整個(gè)濱河市掘鄙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌削锰,老刑警劉巖通铲,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異器贩,居然都是意外死亡颅夺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)蛹稍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吧黄,“玉大人,你說(shuō)我怎么就攤上這事唆姐∞挚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)赵抢。 經(jīng)常有香客問(wèn)我剧蹂,道長(zhǎng),這世上最難降的妖魔是什么烦却? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任宠叼,我火速辦了婚禮,結(jié)果婚禮上其爵,老公的妹妹穿的比我還像新娘冒冬。我一直安慰自己,他們只是感情好摩渺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布简烤。 她就那樣靜靜地躺著,像睡著了一般摇幻。 火紅的嫁衣襯著肌膚如雪横侦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天绰姻,我揣著相機(jī)與錄音丈咐,去河邊找鬼。 笑死龙宏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伤疙。 我是一名探鬼主播银酗,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼徒像!你這毒婦竟也來(lái)了黍特?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锯蛀,失蹤者是張志新(化名)和其女友劉穎灭衷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體旁涤,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翔曲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劈愚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞳遍。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菌羽,靈堂內(nèi)的尸體忽然破棺而出掠械,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布猾蒂,位于F島的核電站均唉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏肚菠。R本人自食惡果不足惜舔箭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望案糙。 院中可真熱鬧限嫌,春花似錦、人聲如沸时捌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奢讨。三九已至稚叹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拿诸,已是汗流浹背扒袖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亩码,地道東北人季率。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像描沟,于是被迫代替她去往敵國(guó)和親飒泻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 本篇文章:自己在混淆的時(shí)候整理出比較全面的混淆方法吏廉,比較實(shí)用泞遗,自己走過(guò)的坑,淌出來(lái)的路席覆。請(qǐng)大家不要再走回頭路史辙,可能...
    Zane_Samuel閱讀 55,330評(píng)論 8 93
  • 聲明 這篇文章更多的是做一個(gè)整理,內(nèi)容來(lái)自于ProGuard官方文檔以及各種博客等佩伤,相關(guān)文章的鏈接在參考目錄里聊倔,感...
    夷陵小祖閱讀 3,675評(píng)論 0 23
  • 混淆是 Android 打包過(guò)程中最重要的流程之一,基本上所有 app 都應(yīng)該開(kāi)啟混淆生巡,增加app的安全性方库。混淆其...
    shenhuniurou閱讀 1,447評(píng)論 0 2
  • 混淆代碼能有效防止被反編譯障斋,防止自己的勞動(dòng)成果被別人竊取; ProGuard是一個(gè)開(kāi)源的Java代碼混淆器纵潦。它可以...
    appzy閱讀 2,292評(píng)論 2 18
  • 什么是代碼混淆 代碼混淆就是將代碼中的各種元素徐鹤,如變量,方法邀层,類和包的名字改寫(xiě)成無(wú)意義的名字返敬,增加項(xiàng)目反編譯后被讀...
    蝸牛家族史閱讀 5,120評(píng)論 1 4