GMTC分享——當插件化遇到 Android P

轉自:https://blog.csdn.net/xinzhou201/article/details/80881604

GMTC分享——當插件化遇到 Android P

手機京東技術團隊 2018-06-30

舉報

GMTC分享——當插件化遇到 Android P前言

 

Android P 來了,插件化將何去何從?Android作爲操作系統涉及的面比較廣,不可能在所有的方面都能走在大家的需求之前,尤其是這幾年,App越來越大,而相應的Android官方給出的方案一直不太符合中國的國情,先是65536問題,再是多團隊協同開發,再到App如何瘦身,這些問題一直困擾着中國的開發者。國內的開發者們在經過了無數高手的實踐之後,在2016、2017年插件化技術越來越成熟,發展到了頂峯,井噴了許多高質量的插件化框架,以應對大型App的開發。2018年,Google官方也終於祭出了大殺器 -- 禁止調用私有API,並推出官方的動態化框架Android App Bundles。 隨着Android P的發佈,使用插件化的你們做好應對方案了嗎?

GMTC分享——當插件化遇到 Android P

 

京東商城資深Android系統架構師,Android組件化技術負責人,致力於Android系統構架和優化,帶領團隊從無到有實現了Aura組件化體系建設。

GMTC分享——當插件化遇到 Android P   導讀

GMTC分享——當插件化遇到 Android P

全球移動技術大會(GMTC):是由InfoQ主辦的全球頂級技術盛會,大會的目的是促進全球移動技術交流,推動國內技術升級。

手機京東開放平臺:基於手機京東數年移動研發技術實踐積累,爲企業移動應用研發提供一站式技術解決方案,幫助企業快速構建高可用移動應用。

Aura:是手機京東開放平臺 Android 端解決方案,提供了適合大型企業開發的模塊化,插件化框架和平臺,可有效提高企業的開發效率。

2018年6月22日,我有幸在北京國際會議中心的GMTC大會上,分享了一個主題《當插件化遇到AndroidP》。分享這個議題的初衷是由於今年Google放出了Android P的開發者預覽版的同時加入了限制App調用非SDK接口的計劃,它這是釋放了一個將會治理目前各種篡改Android系統亂象的信號,隨着這項計劃的推進,將會涉及到國內的很多App,尤其是使用加固和插件化技術的App。作爲App的開發者,早一步重視這個事情,則將會早一步受益,基於這個前提,京東已經開始着手進行此方面的研究和推進工作了。

演講的主題主要分爲以下五個部分:

● 解讀一下Android P的禁令

● 我們一起來學習一下Android官方的動態化框架Android app bundles

● 插件化的路在何方

● 與大家一起分享京東的架構升級和重構是怎麼做的

● 解決京東架構升級中的一些關鍵技術點

Android P 是 google 將在2018年推出的 Android 新版本,將於第三季度發出正式版本,在這之前會有五個預覽版本。在3月份放出第一個預覽版本的時候,宣佈了禁止應用調用系統非SDK接口的消息;在5月初,Google IO 開發者大會上,推出了 Android 的官方動態化框架 Android app bundles。下面篇幅中我將會對這兩個方面進行一個全面解讀,並對可以採取的一些應對方案進行分析和闡述。

 

GMTC分享——當插件化遇到 Android P  Android P 的禁令解讀

GMTC分享——當插件化遇到 Android P

訪問非SDK接口的後果

在 Android 官網上面列出了幾種通過反射調用訪問非SDK接口的方式和引發的後果,從表格中我們看到後果主要有兩個分別是拋出異常和返回的結果列表中沒有私有API接口。

 

實施計劃

但是,Google 並沒有一刀切的直接執行禁令,而是分步驟的進行,給了開發者一個緩衝期去修改自己的App。採用的辦法是維護三個名單,分別是淺灰名單,深灰名單,黑名單:

淺灰名單中的接口還可以繼續在 AndroidP 中使用,但是在未來的版本中就有可能會移到黑名單中,也可能會開發新的public API來供開發者光明正大的使用。

深灰名單中的接口,在Android P 的後續預覽版中將不可訪問,所以如果有使用深灰名單中的接口,必須馬上進行整改。

黑名單中的接口就不允許調用了,如果調用直接就是拋異常等行爲。

 

注意

這個禁令是在 Android P 上起作用,而且針對應用的 target SDK 是否是 28 會有不同的表現;Google Play 要求從 2018 年 8 月份開始應用的最低版本爲 Target SDK 26,明年可能將會要求最低的 Target SDK 爲 28,所以開發者一定要重視。

 

GMTC分享——當插件化遇到 Android P Android App bundles

GMTC分享——當插件化遇到 Android P

Android 官方動態化框架 Android App Bundles,簡稱 AAB,是今年5月初在Google IO 開發者大會上首次亮相,這是官方支持的動態化框架,值得開發者儘快學習和使用。GMTC分享——當插件化遇到 Android P

通過一張動圖來感性的認識一下AAB,左圖是legacy APK,右圖是動態分發 apk, 可以看到左圖是把所有的代碼和資源統統塞到了用戶的App中,所以導致App體積變大,而右圖只把適合用戶手機分辨率和語言等按維度劃分的相關部分動態下發到用戶手機上,這樣能夠極大的減小APK的大小。

 

Android App bundles的內部結構

AAB拆分後主要分爲三種類型的APK,它們分別是Base APK, configuration APKs, Dynamic feature APKs;

Base APK是首次安裝的APK,它提供了應用的基本功能,並且包含其它Splite Apks 可以訪問的代碼和資源;

Configuration Apks包含了特定的屏幕密度,cpu架構和語言資源等,有兩種類型的configuration apk, 一種是 Base Configuration Apks, 一種是 Feature Configuration Apks,當用戶下載Base APK或者Dynamic feature Apk的時候,只需要下載其對應的特定資源;

Dynamic feature Apks是首次安裝的時候不需要的代碼和資源,是由開發者自行定義和開發出來的,在代碼中使用 Play Core Library 動態下載和安裝

 

AAB的整體流程

GMTC分享——當插件化遇到 Android P

 

首先,開發者研發自己的APP,並把它編譯打包成AAB格式,然後上傳到Google Play服務器上;

 

服務器會把客戶的AAB文件拆分成三種類型的APK,並存儲在Google Play的服務器中;

 

當用戶使用時,會從市場上首次安裝Base apk, 然後按需下載 Dynmaic Apk, 對於以上兩種APK, 均有配套對應的 feature configuration APK進行下載。

 

Android App Bundles 總結

優點

● 官方推出的,背景強大

● 通過了兩種方式減小了 APK 的體積,一是去除了與用戶機型不匹配的代碼和資源,二是動態下發首次不需要安裝的部分

 

限制

● 目前只能通過 Google Play發佈

● 處於測試階段,用戶需要申請加入 Google 的 Dynamic feature beta program 計劃才能使用

● 最低支持的版本是 Android 5.0,

● 只是單純的減小了包體積,不能通過動態下發來修復Bug和增加之前未預算的新功能,也不能增加Base Apk的manifest中沒有的四大組件

 

使用成本

● 需要開發者的 IDE 升級到 Android Studio 3.2

● 需要集成 Play Core Library 來支持 dynamic feature 的下載和安裝

● 可以加入 SplitCompat 庫以支持6.0以下的手機來熱更新D ynamic feature apk

● 所有的模塊必須位於同一個工程

● 如果之前的Library想改改造成Dynamic Feature Module 必須手動改造

GMTC分享——當插件化遇到 Android P

 

GMTC分享——當插件化遇到 Android P   插件化的路在何方

GMTC分享——當插件化遇到 Android P

實現插件化的黑科技

插件化的流派比較多,但不管是哪種流派,它們一般都用到了一些黑科技,主要有三種:

● Hook App運行的關鍵點,以達到動態檢測是否調用了插件中的代碼和資源,比如Hook Instrumentation等

● 動態的加載插件中的類,這裏分爲單Class Loader和多Class Loader技術,這兩種技術都用到了反射技術,以達到替換系統的ClassLoader或者是增加自己的Class Path的目的

● 動態的加載插件中的資源,一般會反射調用 AssetManager.addAssetPaths 這個方法.下面這張圖是通過官方的掃描腳本掃描出來的手機京東的插件化框架Aura使用非sdk接口的結果,從中可以看出使用了淺灰名單中的兩個方法 

 

GMTC分享——當插件化遇到 Android P

 

路在何方

當初爲什麼要研發和使用插件化技術,現在我們的真實需要是什麼?

GMTC分享——當插件化遇到 Android P

 

研發和使用插件化技術的原因

● 繞過65536問題,快速啓動

● 模塊解耦

● 多個團隊並行開發

● 加快編譯速度

● 動態部署

 

現在的真實需求

● 去黑科技

● 平穩過渡

● 邊界隔離

● 並行開發

● 獨立調試

● 快速編譯

● 動態部署

 

探索道路

● Follow官方的方案

● 組件化方案

● 大前端:RN, Weex, 快應用等

 

方案對比

功能 插件化 AAB 組件化 前端
邊界隔離 ✔️ ✔️ ✔️ ✔️
並行開發 ✔️ ✔️ ✔️
獨立調試 ✔️ ✔️ ✔️
兼容性
成熟度 黑科技 需研發
動態部署 ✔️ 打折 ✔️
遷移成本 /

這幾個方案各有優缺點,其中AAB方案還不太成熟,前端和AAB的遷移成本都比較高,組件化的方案也需要研發一個適合自己公司的框架。

 

適配步驟

● 增加組件化功能

● 組件化和插件化相結合,具有兩者的優點

● 從長期來看,可以向AAB和前端方向靠攏

● 持續改進和優化,以保持自身的活力

 

手機京東的架構升級和重構

GMTC分享——當插件化遇到 Android P

 

制定重構目標

第一要務就是去除插件化去除黑科技

第二要務是從現有的方案平穩過渡到新方案

第三是我們在重構的過程中順便把京東之前的一個毒瘤去除掉,也就是體積龐大並且中心化的基礎類庫JdLib去中心化

最後是插件和組件可隨時互相轉換

 

升級手機京東的架構

目前京東的插件化框架使用的是阿凡達(Avatar)項目中的 Aura 框架,我們將現在的的插件化框架 Aura 升級到插件化和組件化相結合的 AuraPlus 框架,它具有靈活互轉,無縫調用,優勢互補等優點。

GMTC分享——當插件化遇到 Android P

從圖中,我們看到,一切皆組件,最下層是基礎組件,再往上層是業務組件和業務插件,業務組件是直接依賴基礎組件的,它們中間不再存在JDLIB這個中心化的基礎類庫了。再上層是通過業務模塊任意組合成的京東的應用。

 

GMTC分享——當插件化遇到 Android P 插件化關鍵技術點

GMTC分享——當插件化遇到 Android P

一個核心,四大技術

GMTC分享——當插件化遇到 Android P

一個核心

● 我們是圍繞"高內聚,低耦合"這個核心思想來進行的重構和升級的。

 

四大技術

● 以 Project 和 Module 爲邊界進行組件間物理隔離

● 使用了一個巧妙和靈活的組件間通訊的方式,在自由和隔絕之間尋找到了一個最佳平衡點

● 處理組件間的依賴關係

● 其它的關鍵技術點

 

架構的項目結構

 

我們採用的是一主工程多子工程的開發模型,一切皆組件,組件是採用的小團隊獨立開發的模式。

 

我們這個模型與網上流行的一般的 Library和 Application 承着編譯類型的不同而轉換的方式是不同的,我們這種方式需要在每個組件內實現一個獨立的 Application 殼工程

 

這樣帶來的好處是避免了很多 Library和 Application 互相轉換帶來的坑,比如 ButterKnife 中的 R 和 R2 問題。

 

組件間的通訊

 

GMTC分享——當插件化遇到 Android P

 

組件最終的編譯結果生成了兩個產物,一個是Api.jar,一個是Full.aar

 

當組件需要依賴其它組件時,只需要provided其它組件的Api.jar,而在宿主工程編譯整體APK時,再 Compile Full.aar

 

這種巧妙的方式,能夠在自由和隔離之間找到一個最佳平衡點。

 

組件依賴

GMTC分享——當插件化遇到 Android P

 

我們看一下這個圖,組件A依賴組件B,C,D,組件B依賴組件E。

 

那麼能不能通過依賴傳遞讓組個A再依賴組件E呢,答案是不能,我們制定了一個規則,如果組件A想依賴組件B,則必須明確寫出

 

這樣做的好處是簡化了組件之間的依賴關係,使它們基於接口的依賴更加明確和清晰化。

 

組件提效武林祕籍

GMTC分享——當插件化遇到 Android P

 

前邊我們重構的的結構圖中介紹到,我們去除了 JDLIB 這個龐大而臃腫的基礎類庫,業務組件和業務插件是直接依賴基礎組件的

 

但是常用的基礎組件有好多個,如果每個業務組件都寫一遍的話,則會比較麻煩和重複,這對於追求完(tou)美(lan)的程序員來說是不可接受的

 

所以我們使用 Gradle 插件做了一個薄而靈活的SDK層,這樣,業務組件和業務插件只需要一行代碼即可引入多個常用的基礎組件,起到了原先JDLIB的功能,但又不致於耦合和臃腫。

 

其它祕籍

 

預防資源ID衝突,可以加上resourcePrefix前綴;

 

爲了方便管理第三方庫,做了一個統一管理第三方庫的組件 ThirdBundle;

 

因爲組件對外暴露的API是jar,不能有資源,所以還專門實現了一個BaseResBundle來存放公共資源。