Android 系統上實現APK外掛機制——360手機助手
阿新 • • 發佈:2019-01-26
Droid Plugin
DroidPlugin 是360手機助手在Android系統上實現了一種新的外掛機制:它可以在無需安裝、修改的情況下執行APK檔案,此機制對改進大型APP的架構,實現多團隊協作開發具有一定的好處。
定義:
HOST程式:外掛的宿主。
外掛:免安裝執行的APK
限制和缺陷:
- 無法在外掛中傳送具有自定義資源的
Notification
,例如: a. 帶自定義RemoteLayout的Notification b. 圖示通過R.drawable.XXX指定的通知(外掛系統會自動將其轉化為Bitmap) - 無法在外掛中註冊一些具有特殊Intent Filter的
Service
Activity
、BroadcastReceiver
、ContentProvider
等元件以供Android系統、已經安裝的其他APP呼叫。 - 對
Activity
的LaunchMode支援不夠好,Activity Stack管理存在一定缺陷。Activity的onNewIntent
函式可能不會被觸發。 (此為BUG,未來會修復) - 缺乏對Native層的Hook,對某些帶native程式碼的apk支援不好,可能無法執行。比如一部分遊戲無法當作外掛執行。
特點:
- 支援Androd 2.3以上系統
- 外掛APK完全不需做任何修改,可以獨立安裝執行、也可以做外掛執行。要以外掛模式執行某個APK,你無需重新編譯、無需知道其原始碼。
- 外掛的四大元件完全不需要在Host程式中註冊,支援Service、Activity、BroadcastReceiver、ContentProvider四大元件
- 外掛之間、Host程式與外掛之間會互相認為對方已經"安裝"在系統上了。
- API低侵入性:極少的API。HOST程式只是需要一行程式碼即可整合Droid Plugin
- 超強隔離:外掛之間、外掛與Host之間完全的程式碼級別的隔離:不能互相呼叫對方的程式碼。通訊只能使用Android系統級別的通訊方法。
- 支援所有系統API
- 資源完全隔離:外掛之間、與Host之間實現了資源完全隔離,不會出現資源竄用的情況。
- 實現了程序管理,外掛的空程序會被及時回收,佔用記憶體低。
- 外掛的靜態廣播會被當作動態處理,如果外掛沒有執行(即沒有外掛程序執行),其靜態廣播也永遠不回被觸發。
使用方法:
整合
在host中整合Droid Plugin專案非常簡單:
-
我們只是需要將Droid Plugin當作一個lib工程應用到主專案中,然後:
-
在
AndroidManifest.xml
中使用外掛的com.morgoo.droidplugin.PluginApplication
:<application android:name="com.morgoo.droidplugin.PluginApplication" android:label="@string/app_name" android:icon="@drawable/ic_launcher"
-
如果你使用自定義的
Application
,那麼你需要在自定義的Application classonCreate
和attachBaseContext
方法中新增如下程式碼:@Override public void onCreate() { super.onCreate(); //這裡必須在super.onCreate方法之後,順序不能變 PluginHelper.getInstance().applicationOnCreate(getBaseContext()); } @Override protected void attachBaseContext(Context base) { PluginHelper.getInstance().applicationAttachBaseContext(base); }
-
將外掛中
Libraries\DroidPlugin\AndroidManifest.xml
中所有的provider
對應的authorities
修改成自己的,預設為com.morgoo.droidplugin_stub_P00
,如下:<provider android:name="com.morgoo.droidplugin.stub.ContentProviderStub$StubP00" android:authorities="com.morgoo.droidplugin_stub_P00" android:exported="false" android:label="@string/stub_name_povider" />
可以修改為自己的包名,如:
com.example.droidplugin_stub_P00
防止跟其它本外掛使用者衝突:<provider android:name="com.morgoo.droidplugin.stub.ContentProviderStub$StubP00" android:authorities="com.example.droidplugin_stub_P00" android:exported="false" android:label="@string/stub_name_povider" />
-
整合完成。
安裝、解除安裝外掛:
-
安裝、更新外掛,使用如下方法:
int PluginManager.getInstance().installPackage(String filepath, int flags)
說明:安裝外掛到外掛系統中,
filepath
為外掛apk路徑,flags
可以設定為0,如果要更新外掛,則設定為PackageManagerCompat.INSTALL_REPLACE_EXISTING
返回值及其含義請參見PackageManagerCompat
類中的相關欄位。 -
解除安裝外掛,使用如下方法:
int PluginManager.getInstance().deletePackage(String packageName,int flags);
說明:從外掛系統中解除安裝某個外掛,
packageName
傳外掛包名即可,flags
傳0。 -
啟動外掛:啟動外掛的
Activity
、Service
等都和你啟動一個以及安裝在系統中的app一樣,使用系統提供的相關API即可。元件間通訊也是如此。