这里所说的动态加载是加载一个包(插件),其实就是一个 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();
}
}
其时就是一个工程可以运行 再创建一个工程 把刚才编译的 apk 放到 assets 目录下 assets创建: 先搞清动态加载其实就是把 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();
}
}
});
}
}
运行: 点击就会自动加载: 日志: