Android插件框架VirtualAPK
VirtualAPK是滴滴出行自研的一款優秀的插件化框架,主要有如下幾個特性。
功能完備
- 支持幾乎所有的Android特性;
- 四大組件方面
四大組件均不需要在宿主manifest中預注冊,每個組件都有完整的生命周期。
- 自定義View:支持自定義View,支持自定義屬性和style,支持動畫;
- PendingIntent:支持PendingIntent以及和其相關的Alarm、Notification和AppWidget;
- 支持插件Application以及插件manifest中的meta-data;
- 支持插件中的so。
優秀的兼容性
- 兼容市面上幾乎所有的Android手機,這一點已經在滴滴出行客戶端中得到驗證;
- 資源方面適配小米、Vivo、Nubia等,對未知機型采用自適應適配方案;
- 極少的Binder Hook,目前僅僅hook了兩個Binder:AMS和IContentProvider,hook過程做了充分的兼容性適配;
- 插件運行邏輯和宿主隔離,確保框架的任何問題都不會影響宿主的正常運行。
入侵性極低
- 插件開發等同于原生開發,四大組件無需繼承特定的基類;
- 精簡的插件包,插件可以依賴宿主中的代碼和資源,也可以不依賴;
- 插件的構建過程簡單,通過Gradle插件來完成插件的構建,整個過程對開發者透明。
VirtualAPK和主流開源框架的對比
如下是VirtualAPK和主流的插件化框架之間的對比。
| 支持四大組件 | 只支持Activity | 只支持Activity | 只支持Activity | 全支持 | 全支持 |
| 組件無需在宿主manifest中預注冊 | √ | × | √ | √ | √ |
| 插件可以依賴宿主 | √ | √ | √ | × | √ |
| 支持PendingIntent | × | × | × | √ | √ |
| Android特性支持 | 大部分 | 大部分 | 大部分 | 幾乎全部 | 幾乎全部 |
| 兼容性適配 | 一般 | 一般 | 中等 | 高 | 高 |
| 插件構建 | 無 | 部署aapt | Gradle插件 | 無 | Gradle插件 |
為什么選擇VirtualAPK?
已經有那么多優秀的開源的插件化框架,滴滴為什么要重新造一個輪子呢?
1. 大部分開源框架所支持的功能還不夠全面?除了DroidPlugin,大部分都只支持Activity。
2. 兼容性問題嚴重,大部分開源方案不夠健壯?由于國內Rom嘗試深度定制Android系統,這導致插件框架的兼容性問題特別多,而目前已有的開源方案中,除了DroidPlugin,其他方案對兼容性問題的適配程度是不足的。
3. 已有的開源方案不適合滴滴的業務場景?雖然說DroidPlugin從功能的完整性和兼容性上來看,是一款非常完善的插件框架,然而它的使用場景和滴滴的業務不符。
DroidPlugin側重于加載第三方獨立插件,比如微信,并且插件不能訪問宿主的代碼和資源。而在滴滴打車中,其他業務模塊均需要宿主提供的訂單、定位、賬號等數據,因此插件不可能和宿主沒有交互。
其實在大部分產品中,一個業務模塊實際上并不能輕而易舉地獨立出來,它們往往都會和宿主有交互,在這種情況下,DroidPlugin就有點力不從心了。
基于上述幾點,我們只能重新造一個輪子,它不但功能全面、兼容性好,還必須能夠適用于有耦合的業務插件,這就是VirtualAPK存在的意義。
在加載耦合插件方面,VirtualAPK是開源方案的首選,推薦大家使用。
通俗易懂地說
抽象地說
VirtualAPK的工作過程
VirtualAPK對插件沒有額外的約束,原生的apk即可作為插件。插件工程編譯生成apk后,即可通過宿主App加載,每個插件apk被加載后,都會在宿主中創建一個單獨的LoadedPlugin對象。如下圖所示,通過這些LoadedPlugin對象,VirtualAPK就可以管理插件并賦予插件新的意義,使其可以像手機中安裝過的App一樣運行。?
如何使用
第一步: 初始化插件引擎
@Override protected void attachBaseContext(Context base) {super.attachBaseContext(base);PluginManager.getInstance(base).init(); }第二步:加載插件
public class PluginManager {public void loadPlugin(File apk); }當插件入口被調用后,插件的后續邏輯均不需要宿主干預,均走原生的Android流程。?比如,在插件內部,如下代碼將正確執行:
@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_book_manager);LinearLayout holder = (LinearLayout)findViewById(R.id.holder);TextView imei = (TextView)findViewById(R.id.imei);imei.setText(IDUtil.getUUID(this));// bind service in pluginIntent service = new Intent(this, BookManagerService.class);bindService(service, mConnection, Context.BIND_AUTO_CREATE);// start activity in pluginIntent intent = new Intent(this, TCPClientActivity.class);startActivity(intent); }探究原理
基本原理
- 合并宿主和插件的ClassLoader?需要注意的是,插件中的類不可以和宿主重復
- 合并插件和宿主的資源?重設插件資源的packageId,將插件資源和宿主資源合并
- 去除插件包對宿主的引用?構建時通過Gradle插件去除插件對宿主的代碼以及資源的引用
四大組件的實現原理
- Activity?采用宿主manifest中占坑的方式來繞過系統校驗,然后再加載真正的activity;
- Service?動態代理AMS,攔截service相關的請求,將其中轉給Service Runtime去處理,Service Runtime會接管系統的所有操作;
- Receiver?將插件中靜態注冊的receiver重新注冊一遍;
- ContentProvider?動態代理IContentProvider,攔截provider相關的請求,將其中轉給Provider Runtime去處理,Provider Runtime會接管系統的所有操作。
如下是VirtualAPK的整體架構圖,更詳細的內容請大家閱讀源碼。
總結
以上是生活随笔為你收集整理的Android插件框架VirtualAPK的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现代c++之列表初始化/统一初始化
- 下一篇: android sina oauth2.