1. 程式人生 > >Android多模組混淆、多module混淆、多library混淆的正確姿勢

Android多模組混淆、多module混淆、多library混淆的正確姿勢

部落格中我們提到了混淆。混淆的文章其實網上也很多,介紹的都很好,但是關於多個module的混淆規則就不是這麼詳細,有的也是錯誤的,經過了2天的多次實踐以及查閱資料(多次打包和反編譯看原始碼,很費時間啊),終於達到了我的目的。下面來總結一下。也希望能幫到需要的同學。

Android Studio本身集成了ProGuard混淆工具,我們可以通過編輯build.gradle檔案來開啟混淆並且對程式碼進行壓縮,對資源進行優化等。如下圖

這裡寫圖片描述

下面是程式碼,可以直接複製

    buildTypes {
        release {
            minifyEnabled true
//開啟混淆 zipAlignEnabled true //壓縮優化 shrinkResources true //移出無用資源 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //預設的混淆檔案以及我們指定的混淆檔案 } }

開啟了混淆別忘去proguard-rules.pro檔案編輯混淆規則,混淆規則網上也有很多,自行百度即可。

這裡寫圖片描述

如果你的專案只有一個app module,那麼這樣配置混淆就可以了。但是如果你的專案有好幾個module,module之間還是相互依賴的,那麼該怎麼混淆呢?

混淆方法

1)在app module中統一配置混淆規則
我們可以直接在app module中build.gradle檔案配置所有module需要混淆的規則。這樣,其他module中就無需開啟混淆。但是並不推薦使用這種方法,當我們取消依賴某些module的時候,這樣很容易造成混淆規則冗餘,我們還需要刪除掉該module相關的混淆配置,很麻煩。

2)各個module單獨配置混淆規則(推薦)
我們也可以單獨為module配置混淆規則,比較推薦這種做法。每個module管理自己的混淆檔案,當我們不依賴該module的時候,就不會發生第一種方法出現的問題了。

我們把app module稱作為主模組,其依賴的其他module稱作為子模組

如圖所示。我的app模組是依賴了其他模組的,其他模組也有相互依賴的地方。

這裡寫圖片描述

網上很多關於子module的混淆配置是錯誤的,經過我的多次實踐得出,主模組的混淆開關配置會直接影響到子模組,也就是說如果你的主模組開啟的混淆,就算你的子模組關閉混淆開關,最終子模組還是會被混淆的。
其次
子模組混淆檔案的指定是通過consumerProguardFiles這個屬性來指定的,並不是proguardFiles 屬性,而且我們無需配置其他的選項,只需要配置consumerProguardFiles屬性就可以。該屬性表示在打包的時候會自動尋找該module下我們指定的混淆檔案對程式碼進行混淆。

如果我們釋出出一些開源庫去給別人用,想要對庫程式碼進行混淆的話,也可以通過配置該屬性來達到目的

這裡寫圖片描述

關於多模組混淆的小技巧

一般來說,在元件化開發的情況下,app module的程式碼是很少的,依賴的第三方庫也是很少的。我們可以把通用的混淆規則放到app module中。 這樣子module就無需配置通用混淆規則,只需要配置一些該module所需要的混淆規則即可。大大減少了混淆程式碼。

app module下的混淆規則
這裡給出一個也是從網上找的基本的混淆模板。關於自己專案的實體類和依賴的第三方sdk需要自己新增混淆規則,一般開源庫都會給出混淆規則,沒有的話就要自己百度了

#
#-------------------------------------------基本不用動區域----------------------------------------------
#
#
# -----------------------------基本 -----------------------------
#

# 指定程式碼的壓縮級別 0 - 7(指定程式碼進行迭代優化的次數,在Android裡面預設是5,這條指令也只有在可以優化時起作用。)
-optimizationpasses 5
# 混淆時不會產生形形色色的類名(混淆時不使用大小寫混合類名)
-dontusemixedcaseclassnames
# 指定不去忽略非公共的庫類(不跳過library中的非public的類)
-dontskipnonpubliclibraryclasses
# 指定不去忽略包可見的庫類的成員
-dontskipnonpubliclibraryclassmembers
#不進行優化,建議使用此選項,
-dontoptimize
 # 不進行預校驗,Android不需要,可加快混淆速度。
-dontpreverify


# 遮蔽警告
-ignorewarnings
# 指定混淆是採用的演算法,後面的引數是一個過濾器
# 這個過濾器是谷歌推薦的演算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保護程式碼中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 這在JSON實體對映時非常重要
-keepattributes Signature
# 丟擲異常時保留程式碼行號
-keepattributes SourceFile,LineNumberTable
 #優化時允許訪問並修改有修飾符的類和類的成員,這可以提高優化步驟的結果。
# 比如,當內聯一個公共的getter方法時,這也可能需要外地公共訪問。
# 雖然java二進位制規範不需要這個,要不然有的虛擬機器處理這些程式碼會有問題。當有優化和使用-repackageclasses時才適用。
#指示語:不能用這個指令處理庫中的程式碼,因為有的類和類成員沒有設計成public ,而在api中可能變成public
-allowaccessmodification
#當有優化和使用-repackageclasses時才適用。
#-repackageclasses com.test

 # 混淆時記錄日誌(列印混淆的詳細資訊)
 # 這句話能夠使我們的專案混淆後產生對映檔案
 # 包含有類名->混淆後類名的對映關係
-verbose

#
# ----------------------------- 預設保留 -----------------------------
#
#----------------------------------------------------
# 保持哪些類不被混淆
#繼承activity,application,service,broadcastReceiver,contentprovider....不進行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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 class android.support.** {*;}## 保留support下的所有類及其內部類

-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#表示不混淆上面宣告的類,最後這兩個類我們基本也用不上,是接入Google原生的一些服務時使用的。
#----------------------------------------------------

# 保留繼承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**


#表示不混淆任何包含native方法的類的類名以及native方法名,這個和我們剛才驗證的結果是一致
-keepclasseswithmembernames class * {
    native <methods>;
}


#這個主要是在layout 中寫的onclick方法android:onclick="onClick",不進行混淆
#表示不混淆Activity中引數是View的方法,因為有這樣一種用法,在XML中配置android:onClick=”buttonClick”屬性,
#當用戶點選該按鈕時就會呼叫Activity中的buttonClick(View view)方法,如果這個方法被混淆的話就找不到了
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

#表示不混淆列舉中的values()和valueOf()方法,列舉我用的非常少,這個就不評論了
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#表示不混淆任何一個View中的setXxx()和getXxx()方法,
#因為屬性動畫需要有相應的setter和getter的方法實現,混淆了就無法工作了。
-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);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#表示不混淆Parcelable實現類中的CREATOR欄位,
#毫無疑問,CREATOR欄位是絕對不能改變的,包括大小寫都不能變,不然整個Parcelable工作機制都會失敗。
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
# 這指定了繼承Serizalizable的類的如下成員不被移除混淆
-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();
}
# 保留R下面的資源
-keep class **.R$* {
 *;
}
#不混淆資源類下static的
-keepclassmembers class **.R$* {
    public static <fields>;
}



# 對於帶有回撥函式的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}

# 保留我們自定義控制元件(繼承自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);
}

#
#----------------------------- WebView(專案中沒有可以忽略) -----------------------------
#
#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);
}
#在app中與HTML5的JavaScript的互動進行特殊處理
#我們需要確保這些js要呼叫的原生方法不能夠被混淆,於是我們需要做如下處理:
-keepclassmembers class com.ljd.example.JSInterface {
    <methods>;
}

#(可選)避免Log列印輸出
-assumenosideeffects class android.util.Log {
   public static *** v(...);
   public static *** d(...);
   public static *** i(...);
   public static *** w(...);
 }


子module下的混淆配置 示例

只需要配置改module需要的混淆規則即可,注意我這裡只是個示例,具體的混淆規則根據你的module來定。

這裡寫圖片描述

這樣一來,我們就優雅的完成了多module下的混淆配置。

好了,就這些,希望能幫到你。覺得還行的話點個贊呦。

相關推薦

基於maven使用IDEA搭建和部署SpringBoot模組專案(Multi-Module

What matters in life is not what happens to you but what you remember and how you remember it. 生命中真正重要的不是你遭遇了什麼,而是你記住了哪些事,又是如

Android開發OA幸運飛艇原始碼出售 - 獲取系統輸入法高度的正確姿勢

問題與解決在Android應用的開發中OA幸運飛艇原始碼出售QQ2952777280【話仙原始碼論壇】hxforum.com,有一些需求需要我們獲取到輸入法的高度,但是官方的API並沒有提供類似的方法,所以我們需要自己來實現。 查閱了網上很多資料,試過以後都不理想。 比如有的方法通過監聽佈局的變化來計算輸

電商遊戲旅遊,找對Facebook海外營銷正確姿勢了嗎?

雖然 Facebook 在上週經歷了一輪股價下跌,但這個社交帝國依然堅挺,畢竟它在全球擁有超 20 億活躍使用者,佔世界人口 1/5。 利用 Facebook 平臺來尋找消費者,這是全球很多品牌都玩得溜溜的了。對於中國的品牌及電商、遊戲、旅遊行業,鑑於客觀原因,要玩轉 Facebook

Android模組混淆module混淆library混淆正確姿勢

部落格中我們提到了混淆。混淆的文章其實網上也很多,介紹的都很好,但是關於多個module的混淆規則就不是這麼詳細,有的也是錯誤的,經過了2天的多次實踐以及查閱資料(多次打包和反編譯看原始碼,很費時間啊),終於達到了我的目的。下面來總結一下。也希望能幫到需要的

Android Studio模組的SDK專案打包和混淆

任務遇到的難點 1.SDK專案多模組,編譯後每個模組自己生成了1個jar包。但是需求是隻對外發佈一個jar包,需要進行合併多個jar包。 2.生成的jar包中因為模組引入了百度地圖定位導致jar包內有不需要的asset檔案雜項 3.多模組的混淆問題   解決方案:

PYTHON自動化Day6-函式個返回值和匿名函式列表生成式,三元運算子,os模組,sys模組,時間模組,字典排序,資料庫操作,加密(md5)

一.函式多個返回值和匿名函式 #函式返回多個值,用一個變數接收 def say(): num1=1 num2=2 num3=3 return num1,num2,num3 res=say() print(res) #打印出來是元組。 函式如果返回多個值的話,會把返回的

python學習第34天之udp的套接字套接字的執行緒socketserver模組的使用作業系統理論

一、udp的套接字 Udp協議又叫資料報協議, 特點:每次傳送資料自帶報頭,即使傳送為0也會自帶報頭,所以不會報錯;一端發一次資料。另一端也只能收一次資料 服務端: import socket server=socket.socket(socket.AF_INET,socket.SOCK_DG

SpringBoot專案(單模組模組)使用docker容器執行jar包映象(踩坑)

SpringBoot專案(單模組、多模組)使用docker容器執行jar包映象(踩坑) 1.mavem docker外掛配置 <!--docker 外掛配置--> <build> <finalName>生成jar包的名稱</

SpringBoot 模組專案(module)Service自動注入(@Autowired)空指標錯誤解決

 報錯資訊,這個我是截了上一部分,為了省空間下部分我就用...代替了。 java.lang.NullPointerException at com.jd.impl.UploadServiceImpl.uploadBlock(UploadServiceImpl.java:39)

android框架實現短視訊應用3D手勢旋轉banner控制元件指南針智慧管家等應用原始碼

Android精選原始碼 android智慧管家app原始碼 Android高仿拼多多分類列表 Android百度地圖例項詳解之仿摩拜單車APP RecyclerView的LayoutManager搭建流式佈局 Android自定義View分享——一個圓形

[java基礎]一文理解java執行緒必備的ychronized關鍵字,從此不再混淆

java併發程式設計中最長用到的關鍵字就是synchronized了,這裡講解一下這個關鍵字的用法和容易混淆的地方. synchronized關鍵字涉及到鎖的概念, 在java中,synchronized鎖大家又通俗的稱為:方法鎖,物件鎖 和 類鎖 三種. 先上結論! 1 無論是修飾方法還是修飾程式碼塊都

[java基礎]一文理解java執行緒必備的sychronized關鍵字,從此不再混淆

java併發程式設計中最長用到的關鍵字就是synchronized了,這裡講解一下這個關鍵字的用法和容易混淆的地方.synchronized關鍵字涉及到鎖的概念, 在java中,synchronized

解決springboot模組注入(@Bean@Service@Component)訪問不到的問題

如果你因為Service注入失敗,看過無數文章,甚至看過N份原始碼仍不得要領,希望我能終結你的問題; SpringBoot中Service自動注入很方便,例: Service.class(介面類) ServiceImpl.class(實現類) Controller

使用 多渠道productFlavor客戶版本buildType 模組moudle 配置的 那些點點滴滴

------------------------------------------------------------------------------------------------------------------------------------------

idea建立模組Springboot專案匯入模組刪除模組

前言 在eclipse中有Workspace(工作空間)和 Project(工程)的概念在 IDEA中只有 Project(工程)和 Module(模組)的概念。這個地方剛開始用的時候會很容易理不清

MySQL:記錄的增刪改查單表查詢約束條件表查詢連表子查詢pymysql模組MySQL內建功能

資料操作 插入資料(記錄): 用insert; 補充:插入查詢結果: insert into 表名(欄位1,欄位2,...欄位n) select (欄位1,欄位2,...欄位n) where ...; 更新資料update 語法: update 表名 set 欄位1=

IO模型——阻塞IO非阻塞IO路複用IO非同步IOselectors模組

目錄 一、IO模型介紹   為了更好地瞭解IO模型,我們需要事先回顧下:同步、非同步、阻塞、非阻塞     同步(synchronous) IO和非同步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blo

一個 Yii + vue 專案(6)yii模型模組登陸

簡單講一下模型,之前介紹的AR類全稱是(ActiveRecord 在yii\db\ActiveRecord)用中文描述是活動記錄,是一種特殊的模型,模型呢,是 mvc 裡的 m,yii的模型(yii\base\Model)內建了一些常用的處理,像場景,驗證,載入資料,輸出處理。。。這裡就

kotlin和java混合開發專案,模組,分模組開發,分module,元件化開發

# picture_dx #歡迎能來到這裡 客服機器人美洽第三方完美接入魔窗   該demo用了元件化 為什麼要元件化 近年來,為什麼這麼多團隊要進行元件化實踐呢?元件化究竟能給我們的工程、程式碼帶來什麼好處?我們認為元件化能夠帶來兩個最大的好處: 提高元件複用

Android常見條件篩選選單(美團58)

1.簡單實現 1.1佈局分析:   自定義ListPopuScreenMenuView 繼承自 LinearLayout,大致分為三個部分:上面頭部TabLinearLayout;中間的選單內容menuContainerFrameLayout;下面的半透