android 中的动态加载

这里所说的动态加载是加载一个包(插件),其实就是一个 apk只是这个apk 动态加载而已。
创建一个要动态加载的 apk(插件)
写一个类用于动态加载
//DynamicTest.java

package com.example.liuhailong.idynamic;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
public class DynamicTest {
    public void showPluginWindow(Context context) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("我是插件的对话框");
        builder.setTitle(R.string.app_name);
        builder.setNegativeButton("取消", new Dialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        Dialog dialog = builder.create();
        dialog.show();
    }
}

android 中的动态加载
其时就是一个工程可以运行
android 中的动态加载
再创建一个工程
把刚才编译的 apk 放到 assets 目录下
assets创建:
android 中的动态加载
android 中的动态加载
先搞清动态加载其实就是把 apk 加载到内存所以有读apk,写入的操作
定义一个读 apk 的类,把 apk 写入sdcard的文件
//Utils.java

package com.example.liuhailong.testplugin;

import android.content.Context;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Utils {

    private static final int BUF_SIZE = 2048;

    /**
     * 将插件资源从assets写入到sdcard上
     * @param context 上下文
     * @param assetFile asset目录下的文件名称
     * @param sdCardPath 要写入到sdcard的文件
     */
    public static boolean prepareDex(Context context, String assetFile, File sdCardPath) {
        BufferedInputStream bis = null;
        OutputStream dexWriter = null;
        try {
            bis = new BufferedInputStream(context.getAssets().open(assetFile));
            dexWriter = new BufferedOutputStream(new FileOutputStream(sdCardPath));
            byte[] buf = new byte[BUF_SIZE];
            int len;
            while ((len = bis.read(buf, 0, BUF_SIZE))>0) {
                dexWriter.write(buf, 0, len);
            }
            dexWriter.close();
            bis.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

再写主函数动态加载

package com.example.liuhailong.testplugin;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.content.Context;
import android.os.Bundle;
import android.view.View;

import java.io.File;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";

    //apk文件存放的路径
    private String dexFilePath;

    //解压出dex存储路径
    private File dexFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG, "当前的classloader:" + getClassLoader());
        Log.e(TAG, "系统的classloader:" + ClassLoader.getSystemClassLoader());
        //设置dexFilePath
        dexFilePath = getExternalFilesDir(null).getPath() + File.separator + "plugin.apk";
        System.out.println("dexFilePath:" + dexFilePath);
        dexFile = getDir("dex", 0);
        boolean success = Utils.prepareDex(this, "PluginDemo.apk", new File(dexFilePath));
        if (!success)
            return;
        //创建DexClassLoader
        final DexClassLoader dexClassLoader = new DexClassLoader(dexFilePath, dexFile.getAbsolutePath(), null, getClassLoader());
        findViewById(R.id.open_plug_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Class mClass = dexClassLoader.loadClass("com.example.liuhailong.idynamic.DynamicTest");
                    Log.e(TAG,"mClass的默认classLoader:"+mClass.getClassLoader());
                    Object dynamicTest = mClass.newInstance();
                    Method mMethod = mClass.getDeclaredMethod("showPluginWindow", new Class<?>[]{Context.class});
                    mMethod.setAccessible(true);
                    mMethod.invoke(dynamicTest, MainActivity.this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

android 中的动态加载
运行:
android 中的动态加载
点击就会自动加载:
android 中的动态加载
日志:
android 中的动态加载

猜你喜欢

转载自blog.51cto.com/haidragon/2175747