利用DexClassLoader動態加載dex文件


Java中也有類加載器ClassLoader,其作用是動態裝載Class文件,當我們從網絡下載Class文件,或者在編譯時不參與而在運行時動態調用時就需要用類加載器。由於Android對class文件進行了重新打包和優化,最終APK文件中包含的是dex文件,加載這種文件就需要用到DexClassLoader。

DexClassLoader(dexPath, optimizedDirectory, libraryPath, parent)

dexPath:目標類所在的APK或者jar包,/.../xxx.jar

optimizedDirectory:從APK或者jar解壓出來的dex文件存放路徑

libraryPath:native庫路徑,可以為null

parent:父類裝載器,一般為當前類的裝載器、


插件類Plugin用於在運行時由宿主程序調用

public class Plugin {
	public int add(int a, int b) {
		return a+b;
	}
}
使用jar命令將其打包成jar文件

jar -cvf plugin.jar com/dl/plugin/Plugin.class
使用dx命令將其轉化為android中的類格式dex文件
dx --dex --output=f:\dynamic.jar f:\Plugin.jar
將其放到手機目錄中,比如放到根目錄
adb push F:\dynamic.jar /

在宿主程序中動態加載調用插件類Plugin的add函數

DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
clazz = loader.loadClass("com.dl.plugin.Plugin");
Method add = clazz.getMethod("add", Integer.TYPE,Integer.TYPE);
int result = (Integer) add.invoke(clazz.newInstance(), 1,1);

首先動態加載Plugin類,然后通過反射調用add方法,完整代碼如下
private Button btn;
	private Class<?> clazz;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try {
					if (clazz == null) {
						DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
						clazz = loader.loadClass("com.dl.plugin.Plugin");
					}
					Method add = clazz.getMethod("add", Integer.TYPE,Integer.TYPE);
					int result = (Integer) add.invoke(clazz.newInstance(), 1,1);
					Toast.makeText(MainActivity.this, result+"", 0).show();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}


上面使用反射進行函數調用有些復雜,可以使用接口進行更方便的調用還能保持動態加載的靈活性。項目結構如下,保證接口IPlugin類名一致,包括包名。也可以通過引入jar包的形式來做。

於是就可以通過如下方式調用插件類中的代碼了。

DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
clazz = loader.loadClass("com.dl.plugin.Plugin");
IPlugin obj = (IPlugin) clazz.newInstance();
int result = obj.add(1, 1);

效果:




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM