Android外掛化入門指南

weixin_33727510發表於2017-07-01

最近在瞭解公司的專案,第一次接觸Android外掛化,瞭解其重要性,於是就開始了外掛化的學習。本篇文章把外掛化入門過程中的一些技術點整理下來,方便一些初入門的同學一起學習。

一、Android外掛化介紹

1.含義

所謂外掛化,就是讓我們的應用不必再像原來一樣把所有的內容都放在一個apk中,可以把一些功能和邏輯單獨抽出來放在外掛apk中,然後主apk做到[按需呼叫],這樣的好處是一來可以減少主apk的體積,讓應用更輕便,二來可以做到熱插拔,更加動態化。

2.背景

3985563-686e0a32dca54d28.png

3.優點

3985563-edc7793c43a8c9f7.png

二、Android外掛化基礎

1.外掛化的特點

  1. 應用在執行的時候通過載入一些本地不存在的可執行檔案實現一些特定的功能;

  2. 這些可執行檔案是可以替換的;

  3. 更換靜態資源(比如換啟動圖、換主題、或者用伺服器引數開關控制廣告的隱藏現實等)不屬於動態載入;

  4. Android中動態載入的核心思想是動態呼叫外部的 dex檔案,極端的情況下,Android APK自身帶有的Dex檔案只是一個程式的入口(或者說空殼),所有的功能都通過從伺服器下載最新的Dex檔案完成;

2.需要解決的問題

程式碼載入

類的載入可以使用Java的ClassLoader機制,但是對於Android來說,並不是說類載入進來就可以用了,很多元件都是有“生命”的;因此對於這些有血有肉的類,必須給它們注入活力,也就是所謂的元件生命週期管理;

資源載入

資源載入方案大家使用的原理都差不多,都是用AssetManager的隱藏方法addAssetPath。

3.外掛化必備基礎

①ClassLoader類載入器

要想實現載入外部dex檔案(即外掛)來實現熱部署,那麼必然要把其中的class檔案載入到記憶體中。

其中涉及到兩種ClassLoader:DexClassLoader和PathClassLoader。而DexClassLoader可以載入外部的jar,dex等檔案,正是我們需要的。

關於ClassLoader詳解,見ClassLoader完全解析

②Java反射

因為外掛apk與宿主apk不在一個apk內,那麼一些類的訪問必然要通過反射進行獲取。所以瞭解反射對外掛化的學習是必須的。

關於Java反射,見Java反射詳解

③外掛資源訪問

res裡的每一個資源都會在R.java裡生成一個對應的Integer型別的id,APP啟動時會先把R.java註冊到當前的上下文環境,我們在程式碼裡以R檔案的方式使用資源時正是通過使用這些id訪問res資源,然而外掛的R.java並沒有註冊到當前的上下文環境,所以外掛的res資源也就無法通過id使用了。

檢視原始碼,通過“addAssetPath”方法重新生成一個新的Resource物件來儲存外掛中的資源,避免衝突。

關於外掛資源訪問,見使用外掛中的R資源

④代理模式

外掛化實現的過程主要靠欺上瞞下,坑蒙拐騙來實現。想想雖然載入進來了Activity等元件,但也僅僅是最為一個物件而存在,並沒有在AndroidManifest中註冊,沒有生命週期的回撥,並不能實現我們想要的效果。因此無論是dynamic_load_apk通過代理activity來操控外掛activity的方式,還是DroidPlugin通過hook activity啟動過程來啟動外掛activity的方式,都是對代理模式的應用。

關於代理模式,見靜態代理與動態代理

至此,通過ClassLoader載入,然後通過代理模式讓Activity等元件具有生命週期實現真正的功能,並且解決了資源訪問問題。可能外掛化已經可以簡單的實現一些初步的功能,然而外掛化絕不止於此。更多的內容仍需要進一步探索,不過以上知識是基礎中的基礎,必備之必備。

三、Android外掛化開源專案

3985563-d14b0906078e525b.png

介紹一下其中比較重要的兩個,實現思想不同,也是入門外掛化可以學習的兩個。

Dynamic-load-apk

Dynamic-Load-Apk簡稱DL,這個開源框架作者是任玉剛,他的實現方式是,在宿主中埋一個代理Activity,更改ClassLoader後找到載入外掛中的Activity,使用宿主中的Activity作為代理,回撥給外掛中Activity所以對應的生命週期。這個思路與AndroidDynamicLoader有點像,都是做一個代理,只不過Dynamic-load-apk載入的外掛中的Activity。
專案地址:https://github.com/singwhatiwanna/dynamic-load-apk

DroidPlugin

DroidPlugin是張勇實現的一套外掛化方案,它的原理是Hook客戶端一側的系統Api。
專案地址:https://github.com/DroidPluginTeam/DroidPlugin

既然著重介紹了兩個專案,必然要學起來,怎麼學習呢?

好在已經有前人把自己的學習經驗分享出來,那麼我們只需要結合原始碼進行學習即可。

四、Dynamic-load-apk詳解

Android外掛化學習之路(一)之動態載入綜述
Android外掛化學習之路(二)之ClassLoader完全解析
Android外掛化學習之路(三)之呼叫外部.dex檔案中的程式碼
Android外掛化學習之路(四)之使用外掛中的R資源
Android外掛化學習之路(五)之代理Activity
Android外掛化學習之路(六)之動態建立Activity
Android外掛化學習之路(七)之DL外掛開發該注意的坑
Android外掛化學習之路(八)之DynamicLoadApk 原始碼解析(上) Android外掛化學習之路(九)之DynamicLoadApk 原始碼解析(下)

五、DroidPlugin詳解

Hook機制之動態代理
Hook機制之Binder Hook
Hook機制之AMS&PMS
Activity生命週期管理
外掛載入機制
廣播的管理
Service的外掛化
ContentProvider的外掛化

六、總結

以上內容僅是Android外掛化的入門知識,目前認知尚淺。

外掛化、熱更新等技術在2016開始迅速發展,這即是業務發展的需求,也是我們需要緊跟前沿學習的技術。

相關文章