android基於類裝載器DexClassloader設計“外掛框架”
阿新 • • 發佈:2019-02-10
外掛相關介紹
首先外掛只是一個邏輯概念,而不是什麼技術標準,主要包含如下幾個意思:
外掛程式
主程式的程式碼修改成使用介面:
- 外掛不能獨立執行,必須執行一個宿主程式中,宿主程式去呼叫外掛(ps:微信的遊戲算不算外掛?感覺算是一種)
- 外掛一般情況下可以獨立安裝,android中就可以設計一個apk
- 宿主程式中可以管理外掛,比如新增,刪除,禁用等。
- 宿主程式應該保證外掛向下相容,新的宿主程式應該相容老的外掛
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- useDexClassLoader2();
- }
- @SuppressLint("NewApi") privatevoid useDexClassLoader2(){
-
//建立一個意圖,用來找到指定的apk
- Intent intent = new Intent("com.suchangli.android.plugin", null);
- //獲得包管理器
- PackageManager pm = getPackageManager();
- List<ResolveInfo> resolveinfoes = pm.queryIntentActivities(intent, 0);
- //獲得指定的activity的資訊
-
ActivityInfo actInfo = resolveinfoes.get(0
- //獲得包名
- String pacageName = actInfo.packageName;
- //獲得apk的目錄或者jar的目錄
- String apkPath = actInfo.applicationInfo.sourceDir;
- //dex解壓後的目錄,注意,這個用宿主程式的目錄,android中只允許程式讀取寫自己
- //目錄下的檔案
- String dexOutputDir = getApplicationInfo().dataDir;
- //native程式碼的目錄
- String libPath = actInfo.applicationInfo.nativeLibraryDir;
- //建立類載入器,把dex載入到虛擬機器中
- DexClassLoader calssLoader = new DexClassLoader(apkPath, dexOutputDir, libPath,
- this.getClass().getClassLoader());
- //利用反射呼叫外掛包內的類的方法
- try {
- Class<?> clazz = calssLoader.loadClass(pacageName+".Plugin1");
- CommonInterface obj = (CommonInterface)clazz.newInstance();
- int ret = obj.function1(1, 13);
- Log.i("Host", "return result is " + ret);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- }
- package com.suchangli.plugin1;
- import com.suchangli.plugin.CommonInterface;
- publicclass Plugin1 implements CommonInterface{
- publicint function1(int a, int b){
- return a+b;
- }
- }
- privatevoid useDexClassloader3(){
- //建立一個意圖,用來找到指定的apk
- Intent intent = new Intent("com.suchangli.android.plugin", null);
- //獲得包管理器
- PackageManager pm = getPackageManager();
- List<ResolveInfo> resolveinfoes = pm.queryIntentActivities(intent, 0);
- //獲得指定的activity的資訊
- ActivityInfo actInfo = resolveinfoes.get(0).activityInfo;
- //獲得包名
- String pacageName = actInfo.packageName;
- try {
- Resources res = pm.getResourcesForApplication(pacageName);
- int id = 0;
- id = res.getIdentifier("ic_launcher", "drawable", pacageName);
- Log.i("", "resId is " + id);
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }
- }