android DexClassLoader动态加载技术详解
介绍
实例
准备工作
package com.demo.dex; /** * 对外接口 * * @author edsheng * */ public interface Iinterface { public void call(); public String getData(); }
然后是Iclass.java
package com.demo.dex; import android.content.Context; import android.widget.Toast; public class IClass implements Iinterface { private Context context; public IClass(Context context) { super(); this.context = context; } @Override public void call() { Toast.makeText(context, "call method", 0).show(); } @Override public String getData() { return "hello,i am from IClass"; } }注意上面的实现类,在构造的时候我给它传递了以Context对象,为什么要这样呢?因为在android里面什么东西不都是通过context来获取的吗?我这里为了实验就只调用了一下toast。
dx --dex --output=testdex.jar test.jar
正式开始
然后贴出FileUtil.java的代码
package com.demo.utile; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import android.content.Context; import android.os.Environment; public class FileUtile { public static void CopyAssertJarToFile(Context context, String filename, String des) { try { File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + des); if (file.exists()) { return; } InputStream inputStream = context.getAssets().open(filename); file.createNewFile(); FileOutputStream fileOutputStream = new FileOutputStream(file); byte buffer[] = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != 0) { fileOutputStream.write(buffer, 0, len); } fileOutputStream.close(); fileOutputStream.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }这个类主要的作用就是把我们的jar相当于解压到一个目录下面。我这里是解压到外置设备上的其实这样做的安全性并不高,但是为了方便我就这样做了,建议是解压到包目录下面。记住别忘了给应用加权限!!!!!文件读写权限!!!!
package com.demo.activity; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Environment; import com.demo.utile.FileUtile; import dalvik.system.DexClassLoader; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); FileUtile.CopyAssertJarToFile(this, "testdex.jar", "testdex.jar"); File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + "testdex.jar"); final File optimizedDexOutputPath = getDir("temp", Context.MODE_PRIVATE); DexClassLoader classLoader = new DexClassLoader(file.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader()); try { Class<?> iclass = classLoader.loadClass("com.demo.dex.IClass"); Constructor<?> istructor = iclass.getConstructor(Context.class); //利用反射原理去调用 Method method = iclass.getMethod("call", null); String data = (String) method.invoke(istructor.newInstance(this), null); System.out.println(data); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }其实这样调用还有一点要注意的是我感觉这样做每次都要去调用反射,总给我感觉来说不太友好,那么这里我有给出了下面一种写法,这种写法最主要的地方是,要获得Iinterface这个接口,把Iinterface.java这个文件复制到你的工程里面,记得包名相同,调用的时候我们可以这样来调用它。
Class<?> iclass = classLoader.loadClass("com.demo.dex.IClass"); Constructor<?> istructor = iclass.getConstructor(Context.class); Iinterface iinterface = (Iinterface) istructor.newInstance(this); String data = iinterface.getData(); iinterface.call(); Toast.makeText(this, data, 0).show();这样是不是看起来更舒服呢?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。