前言
我在很久之前就想寫一系列關於外掛化的部落格,可是總被這樣或那樣的事情打斷。上週終於鼓足勇氣給自己定了一個計劃:5月10日之前寫完外掛化系列。今天這篇文章是一個開篇,作用有兩個:一是把吹的牛釋出到網上,前面已經說過了;二是對外掛化的知識做一個簡單的介紹,順便幫自己整理一下接下來的寫作思路。
什麼是外掛化
通常,我們的app只有一個apk檔案。而外掛化是一種將app拆分為多個apk的技術,每一個apk都是app功能的一部分。一般,我們把app啟動時由系統載入的apk稱之為宿主。而宿主是可以載入其他的apk的,這些被宿主載入的apk我們稱為外掛。
外掛化的用途
在學習一項新技能之前,我們首先要弄清楚它能為我們帶來什麼。那外掛化能給我們帶來什麼呢?
-
從專案管理角度來說:
- 外掛化將應用的不同功能劃分到一個個的外掛中,便於程式的維護。
- 每個外掛可以單獨執行除錯極大的提高了開發效率。
- 每個外掛互不影響,多人協同開發更加高效。
-
從程式執行角度來說:
- 按需載入外掛,佔用記憶體更少。
- 按需更新,更省流量。
-
從公司運營角度來說:
- 實時更新,便於運營推廣。
- 修復線上BUG,將風險降到最低。
外掛化需要哪些內功
外掛化像是一門十分高深的武功,它需要修習者有一定理論基礎後才能修煉。那它需要哪些理論支撐呢?
-
ClassLoader
ClassLoader是由JVM平臺提供的類載入器。它允許程式從網路、硬碟甚至是記憶體載入Class,這就為Android外掛化提供了最基礎的技術保障。我們知道Android平臺對位元組碼檔案作了優化,摒棄了傳統JVM需要的.jar檔案,而是採用體積更小的.dex檔案。因此,Android自定義了一系列ClassLoader以滿足對dex載入。在這些ClassLoader中,有一個DexClassLoader,它允許我們的app載入外部的.jar和.apk檔案。
-
反射和Hook技術
Hook的翻譯是"鉤子"。我們知道Android作業系統有一套自己的機制,例如,Activity啟動流程、事件分發機制、資源管理機制等。有時候,這些機制無法滿足我們的需求,通過系統的API也無能為力。這時候就需要Hook技術對原有流程進行攔截,然後將系統流程替換成我們自己的流程。而反射是Hook技術的一種必要手段。
-
APP安裝過程
我們知道apk檔案中包含了app執行需要的Activity、Service等資訊。這些資訊是在程式安裝過程中通過PackageManagerService解析AndroidManifest檔案取得的。只有瞭解了這些原理,我們才能知道如何解析外掛中的Activity、Service等資訊。
-
四大元件的啟動流程
單純解析出外掛的Activity、Service等資訊是不行,我們期望的是這些Activity、Service等可以像我們普通App中的一樣可以正常執行。這就需要我們去熟悉四大元件的啟動流程,然後通過Hook技術加入宿主啟動外掛的Activity、Service等邏輯。
-
資源管理
外掛化會給資源管理帶來兩個問題:
-
在Android打包編譯時,gradle會為圖片、文案等資源生成一個唯一的Id。在執行期,通過對資源Id的引用來查詢相應的資源。由於宿主apk和各外掛apk打包不是在一次gradle assemble命令中完成的,這就有可能造成多個apk中產生的資源id相同,我們稱之為資源衝突
-
各apk中的資源是無法共享的,例如在宿主中無法引用外掛中的資源。
為了解決這兩個問題,我們有必要掌握Android平臺的資源管理機制。
-
後續文章會以什麼樣的方式呈現
後續文章我會採用原理+DEMO的表現形式。在每篇文章的前半部分主要是介紹原理知識;後半部分是程式碼Demo,這些Demo串聯在一起就是一個簡單的外掛化框架。