Android 插件化開發(二):加載外部Dex文件

在學習Java反射的技術後,咱們能夠開始由淺入深探究插件化開發了。git

咱們能夠從最基本的加載外部apk開始,而後再到加載插件中的類,而後在經過優化前面實現的時候發現的問題,一步步探究插件化的本質。github

加載流程以下:app

  1. 將插件 apk 放到主 app 的 assets 目錄中,app啓動後把 assets 目錄中的插件 apk 複製到內存。
  2. 讀取插件 apk 中的 dex,生成對應的 DexClassLoader。
  3. 使用 DexClassLoader 的 loadClass 方法讀取插件的 dex 中的任何一個類。

1. 打包插件 apk 並放到宿主 assets 目錄

插件apk能夠按照正常打包應用的方式打包。學習

例如在插件apk裏面寫一個bean類:優化

public class Bean {
    private String name = "jianqiang";

    public String getName() {
        return name;
    }

    public void setName(String paramString) {
        this.name = paramString;
    }
}

打包完成後,放到宿主app項目目錄下的assets目錄下。ui

2. 將assets目錄下的apk複製到/data/data/files目錄下

/**
     * 把Assets裏面得文件複製到 /data/data/files 目錄下
     *
     * @param context
     * @param sourceName
     */
    public static void extractAssets(Context context, String sourceName) {
        AssetManager am = context.getAssets();
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            is = am.open(sourceName);
            File extractFile = context.getFileStreamPath(sourceName);
            fos = new FileOutputStream(extractFile);
            byte[] buffer = new byte[1024];
            int count = 0;
            while ((count = is.read(buffer)) > 0) {
                fos.write(buffer, 0, count);
            }
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeSilently(is);
            closeSilently(fos);
        }
    }

3. 讀取插件 apk 中的 dex,生成對應的 DexClassLoader

DexClassLoader classLoader = new DexClassLoader(dexpath, fileRelease.getAbsolutePath(), null, getClassLoader());

4. 使用 DexClassLoader 的 loadClass 方法讀取插件的 dex 中的類

Class mLoadClassBean;
try {
    mLoadClassBean = classLoader.loadClass("jianqiang.com.plugin1.Bean");
    Object beanObject = mLoadClassBean.newInstance();
    Method getNameMethod = mLoadClassBean.getMethod("getName");
    getNameMethod.setAccessible(true);
    String name = (String) getNameMethod.invoke(beanObject);
    mTextView.setText(name);
    Toast.makeText(getApplicationContext(), name, Toast.LENGTH_LONG).show();
} catch (Exception e) {
    e.printStackTrace();
}

當咱們看到輸出了咱們在插件apk定義的內容後,就說明咱們成功的加載外部的dex並進行調用。this

上述內容的代碼倉庫地址爲:https://github.com/renhui/RHPluginProgramming/tree/master/HostAppspa

相關文章
相關標籤/搜索