android jar包插件化以及遠程更新jar包思路

首先介紹一下要實現的效果:靜默更新所有客戶端應用程序中的jar包。

產生這個需求的原因:當做好的jar包發佈出去,開發者已經在使用的情況下,有一天我們發現jar包中有個bug,這是我們就要去更新jar包,但是如果開發者需要更新jar包的話,那代價無疑是巨大的。出於減少開發者更新jar包的代價的目的。我們想到了使用這種方式來解決。整個項目的結構如下圖:


插件管理框架工作流程:

客戶端app啓動時,插件管理框架讀取本地所有插件信息,例如插件版本,提供者等等,並將該信息發送到插件管理服務端,在服務端監測是否有新的插件需要更新。如果有新的插件插件管理框架負責下載等操作。

具體的實現的話,爲了統一,我們在插件管理框架中定義好接口,所有插件都要實現該接口,實現該接口的插件,我們就認爲它是一個合法的插件。這樣在application中我們就可以通過插件管理框架中的方法來調用插件中的方法。

插件管理框架主要模塊:

1.插件管理:讀取插件信息和服務端交互,根據返回判斷是否下載新的插件。

2.調用插件中的方法。

       關於第一點就不多少了,就是一些網絡訪問和下載的東東。我們主要說一下調用插件中的方法。在使用jar包的使用我們知道如果是放在lib目錄下,通過build path 加載到項目中,我們可以直接通過import導入使用jar包中的類和方法。但是插件的類和方法該怎麼使用呢?這是我們就要使用到android的類加載器。android中有兩種類加載器 DexClassLoader和PathClassLoader,兩者的區別就是PathClassLoader只能加載已經安裝到android系統中的apk文件,也就是/data/app/下的apk文件,加載其他位置的文件會報ClassNotFoundException ,DexClassLoader可以加載apk、jar和dex文件,而且可以加載sdcard下的文件。

先介紹一下我們的插件項目,該項目就是簡單的做個加法運算。

package com.apkplug;

public class plugClass {

    public plugClass() {
        
    }
    public int  add(int a, int b){
        return a+b;
        
    }

    
}

  在下面的介紹中我們使用DexClassLoader.首先我們來打包jar包並轉換成dex文件,首先將寫好的jar包導出,Export->java jarfile ->Next 然後選擇jar的存放目錄。然後我們將jar包轉成dex格式,爲了方便我們將jar包放到SDK的安裝目錄plarform-tools下,DOS進入這個目錄,執行命令: dx --dex -ouput=classes.jar  Myplug.jar 這樣我們就將Myplugin.jar轉成了dex格式,我們將classes.jar 放到SDcard目錄。下面在程序中我們使用DexClassLoader來加載classes.jar中的類

package com.apkplugtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;

public class MainActivity extends Activity {
    TextView tv = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        useDexClassLoader();
    }

    private void useDexClassLoader() {
       
        String dexPath = "/mnt/sdcard/classes.jar";
        String dexOutputDir = "/data/data/com.apkplugtest";

        DexClassLoader pathClassLoader = new DexClassLoader(dexPath, dexOutputDir, null, this
                .getClass().getClassLoader());
        // dexPath 目標jar或apk的路徑 ; dexOutputDirdex 文件路徑 ;null 目標類中使用的c/c++庫存放的路徑
        // ; 第四個參數 父裝載類
        try {
            Class<?> class1 = pathClassLoader.loadClass("com.apkplug.plugClass");
            Object object = class1.newInstance();
            Class[] params = new Class[2];
            params[0] = Integer.TYPE;
            params[1] = Integer.TYPE;
            Method action = class1.getMethod("add", params);
            Integer ret = (Integer) action.invoke(object, 12, 13);
            tv.setText("method : " + action.getName() + ", return :" + ret);
        } catch (Exception e) {
            // TODO: handle exception
        }

    }

   

}

程序運行結果如下圖:


同時我們看到在data/data/com.apkplugtest下生成了.dex 文件如下圖:



整個思路就是這樣了。

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