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

相关文章
相关标签/搜索