Android Plugin 插件化技術-Small插件框架

目錄(?)[+]

本篇文章只是整理了一些流行的開源插件化技術,其中言論純屬開源作者,不代表本人觀點。

一、Small 簡介:做最輕巧的跨平臺插件化框架


  • 完美內置

    • 所有插件支持內置於宿主包中

  • 高度透明

    • 插件編碼、佈局編寫方式與獨立應用開發無異

    • 插件代碼調試與整包開發無異

  • 極致剪裁

    • 對插件分離所有一切能分離的公共代碼、資源

  • 無縫鏈接

    • 通過設定URI,宿主、本地化應用插件、本地化web插件、在線網頁,以及任何自定義的插件之間能夠相互調起與傳遞參數

  • 跨平臺

    • 目前已支持Android、iOS以及html5插件。並且三者之間可以通過同一套javascript接口進行通信。

二、Small Android(支持平臺:Android API 15(4.0.3))


各個插件框架功能對比:

  DyLA  : Dynamic-load-apk          @singwhatiwanna, 百度
  DiLA  : Direct-Load-apk           @melbcat
  APF   : Android-Plugin-Framework  @limpoxe
  ACDD  : ACDD                      @bunnyblue
  DyAPK : DynamicAPK                @TediWang, 攜程
  DPG   : DroidPlugin               @cmzy, 360
  • 功能

    \DyLADiLAACDDDyAPKDPGAPFSmall
    加載非獨立插件[1]×x×
    加載.so插件××[2]×××
    Activity生命週期×
    Service動態註冊××××[3]
    資源分包共享[4]××[5][5]×[6]
    公共插件打包共享[7]××××××
    支持AppCompat[8]××××××
    支持本地網頁組件××××××
    支持聯調插件[9]×x××××
  • [1] 獨立插件:一個完整的apk包,可以獨立運行。比如從你的程序跑起淘寶、QQ,但這加載起來是要鬧哪樣?
         非獨立插件:依賴於宿主,宿主是個殼,插件可使用其資源代碼並分離之以最小化,這纔是業務需要嘛。
         -- “所有不能加載非獨立插件的插件化框架都是耍流氓”

  • [2] ACDD加載.so用了Native方法(libdexopt.so),不是Java層,源碼似乎未共享。

  • [3] Service更新頻度低,可預先註冊在宿主的manifest中,如果沒有很好的理由說服我,現不支持。

  • [4] 要實現宿主、各個插件資源可互相訪問,需要對他們的資源進行分段處理以避免衝突。

  • [5] 這些框架修改aapt源碼、重編、覆蓋SDK Manager下載的aapt,我只想說“殺(wan)雞(de)焉(kai)用(xin)牛(jiu)刀(hao)”
         Small使用gradle-small-plugin,在後期修改二進制文件,實現了PP段分區。

  • [6] 使用public-padding對資源id的TT段進行分區,分開了宿主和插件。但是插件之間無法分段。

  • [7] 除了宿主提供一些公共資源與代碼外,我們仍需封裝一些業務層面的公共庫,這些庫被其他插件所依賴。
         公共插件打包的目的就是可以單獨更新公共庫插件,並且相關插件不需要動到。

  • [8] AppCompat: Android Studio默認添加的主題包,Google主推的Metrial Design包也依賴於此。大勢所趨。

  • [9] 聯調插件:使用Android Studio調試宿主時,可直接在插件代碼中添加斷點調試。

  • 透明度

    \ACDDDyAPKAPFSmall
    插件Activity代碼無需修改
    插件引用外部資源無需修改name×××
    插件模塊無需修改build.gradle×x×

三、Small Android 集成步驟:

Step 1. Clone Small (下載源碼)

> cd [你要放Small的目錄]
> git clone https://github.com/wequick/Small.git

強烈建議使用git命令行,方便更新維護。Windows用戶入口:Git for Windows
後續更新可以使用命令:git pull origin master

Step 2. Import Sample project (導入示例工程)

打開Android Studio,File->New->Import Project... 選擇Sample文件夾,導入。

Small sample

  • Sample 示例工程

    • app 宿主工程

    • app.* 包含Activity/Fragment的組件

    • lib.* 公共庫組件

    • web.* 本地網頁組件

    • sign 簽名文件

順便說下,這些app.*跟web.*可以從工具欄的按鈕單獨運行。
其中app.home無法單獨運行是因爲它只包含一個Fragment,沒有Launcher Activity。

Step 3. Build libraries (準備基礎庫)

> [./]gradlew buildLib -q (-q是安靜模式,可以讓輸出更好看,也可以不加)

Build libraries

Step 4. Build bundles (打包所有組件)

> [./]gradlew buildBundle -q (-q是安靜模式,可以讓輸出更好看,也可以不加)

Build bundles

步驟3跟4,如果你喜歡,也可以在Gradle任務導航裏運行
Small tasks

單獨編譯一個組件可以使用 [./]gradlew -p web.about assembleRelease
或者
Sub tasks

Step 5. Import DevSample project (導入開發工程)

打開Android Studio,File->New->Import Project... 選擇DevSample文件夾,導入。

Small devsample

  • DevSample 開發工程

    • buildSrc 組件編譯插件,用於打包組件

    • small 核心庫,用於加載組件

buildSrc在修改後會被自動編譯。

其他步驟同上。除了編譯單個組件的命令有所不同:

> [./]gradlew :app.main:assembleRelease

P.s. gradlew命令支持縮寫,比如assembleRelease可以縮寫爲aR


四、實現Android插件化的核心技術:

  1. Android dynamic load classes

  2. Android dynamic load resources

  3. Android dynamic register activities

五、常見問題 FAQ 

  1. 插件是否一定得內置到APK中,如果一定要內置,那這個框架僅僅是爲了開發工程中解耦?

    內置是爲了首次啓動更快,如果不內置也行,可以在啓動頁下載插件。

  2. 目前開源的插件開發框架有很多,Small 跟這些框架的區別是什麼,優缺點呢?

  • 把核心代碼量控制在了一個文件(ApkBundleLauncher)500行以內

  • 不修改aapt源碼,實現了資源id PP段的再分配(原理見Dynamic load resources

  • 通過對aapt生成的二進制文件的後期加工,最大化分離無用的資源,使得插件包最小達到4k左右

  • 支持對本地化網頁進行插件打包,實現跨平臺

  1. dynamic-load-apk使用代理的方式實現Activity生命週期,插件中不能用this,不夠透明;

  2. Direct-Load-apk對dynamic-load-apk進行了改進,支持this。但也是用代理Activity,實現較爲繁瑣;

  3. Android-Plugin-Framework是一個相對完整的框架,但資源分區方案還不夠理想,不支持加載.so插件;

  4. ACDD 使用了osgi,沒有細看。。坑點是資源分區要使用修改aapt源碼再重新編譯的方案;

  5. DynamicAPK 坑點:修改aapt源碼,不支持.so插件;

  6. DroidPlugin支持對完整apk的動態加載,但是沒有關於非獨立插件的加載(資源分區要複雜得多);

  7. 這些框架似乎都不支持AppCompat包(但這很重要,材料設計的Design包等都依賴AppCompat);

  8. Small的開發其實是跟隨1、2、3走過來的。從實際場景出發,基於“輕量、透明、極小化、跨平臺”的理念:

  9. 百度工程師開發的 Dynamic-load-apk

  10. melbcat開源的 Direct-Load-apk

  11. limpoxe開源的 Android-Plugin-Framework

  12. bunnyblue開源的 ACDD

  13. 攜程工程師開發的 DynamicAPK

  14. 360工程師開發的 DroidPlugin

目前大多插件框架對Service的支持不太好,Small是否支持,支持度怎麼樣。支持動態加載,不支持動態註冊。實際場景中,Service的更新頻度較低,註冊可以預埋在宿主的manifest文件中。插件與宿主必須運行在同一個進程嗎? 是否支持插件運行在單獨的進程中。在同一個進程。當插件與宿主共有一個控件時(比方說自己寫了一個下拉刷新的控件),開發過程中是不是要插件和宿主裏面都含有這個控件? 同樣,是否允許插件訪問宿主的資源(比如說res)以及數據(SharedPreferences中的數據)。插件中所有的公共資源、類將會被分離。宿主、各個插件之間的資源可以互相訪問,支持SharedPreferences,完全透明。

  • 0

  • 0

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章