zoukankan      html  css  js  c++  java
  • 利用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);

    效果:



  • 相关阅读:
    【开学季】自学嵌入式开发|四核开发板|4412开发板|ARM+Android+linux技术
    迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解
    【嵌入式开发板】8月终极暑促迅为Cortex-a9四核入门开发板
    [资料分享]迅为iTOP4412开发板-SDIO WiFi移植文档
    [leetcode] 905. Sort Array By Parity [easy]
    [leetcode] 106. Construct Binary Tree from Inorder and Postorder Traversal(medium)
    [leetcode] 4. Median of Two Sorted Arrays
    [leetcode] 3. Longest Substring Without Repeating Characters
    [leetcode] 105. Construct Binary Tree from Preorder and Inorder Traversal (Medium)
    [leetcode] 110. Balanced Binary Tree (easy)
  • 原文地址:https://www.cnblogs.com/qhyuan1992/p/5385267.html
Copyright © 2011-2022 走看看