有时候我们需要使用动态更新技术,简单来说就是:当我们把开发jar包发送给用户后,如果后期升级了部分代码,这时让用户的jar包自动更新,而不是用户主动手动地去更新的技术就是动态更新。这个需要使用的技术之一就是Android动态加载JAR包。
主要的过程分为两步,一个是将需要导出的java文件导出位jar包,java文件代码如下所示:
package adapter;
public class RoutePlanManager {
private String name = "RoutePlanManager";
public static String get() {
return "hello world";
}
}
导出为Hello.jar,这时我们需要使用Android SDK提供的工具(在platform-tools目录下),有些版本的没有,可以网上下载。利用dx工具,将java的jar包转为Android虚拟机可以认识的字节码。具体来说,就是执行如下的命令:
dx --dex --output=dex.jar Hello.jar其中,Hello.jar是我们的源jar包,dex.jar是我们用dx工具处理后的jar包,是Android虚拟机可以识别的jar文件,接下来就可以进行第二步操作了。
这里,我们需要使用DexClassLoader类实现Jar的动态加载,该类构造方法的官方文档如下所示:
public DexClassLoader (String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)
Added in API level 3
Creates a DexClassLoader that finds interpreted and native code. Interpreted classes are found in a set of DEX files contained in Jar or APK files.
The path lists are separated using the character specified by the path.separator system property, which defaults to :.
Parameters
dexPaththe list of jar/apk files containing classes and resources, delimited by File.pathSeparator, which defaults to ":" on Android
optimizedDirectorydirectory where optimized dex files should be written; must not be null
libraryPaththe list of directories containing native libraries, delimited by File.pathSeparator; may be null
parentthe parent class loader该接口具有四个参数,第一个是dex.jar包的路径,第二个可以认为是挂载路径,就是优化后的dex文件的存放路径,对权限有要求,所以需要通过上下文获取路径,第三个参数设置为null,第四个代表父亲类加载器。
我们在Android中实现动态加载的代码如下所示:
String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();
String jarPath = sdcard + "/Jar/dex.jar";
String tmpPath = getApplicationContext().getDir("Jar", 0).getAbsolutePath();
DexClassLoader cl = new DexClassLoader(jarPath, tmpPath
, null, this.getClass().getClassLoader());
Class> libProviderCls = null;
try {
libProviderCls = cl.loadClass("adapter.RoutePlanManager");
Constructor> localConstructor = libProviderCls.getConstructor(new Class[] {});
Object obj = localConstructor.newInstance(new Object[] {});
Method mMethodWrite = libProviderCls.getDeclaredMethod("get");
mMethodWrite.setAccessible(true);
String str = (String) mMethodWrite.invoke(obj);
Toast.makeText(LoadJarActivity.this, str, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}当加载了Jar包之后,我们需要执行Jar包中的方法,这个时候我们需要使用Java的反射来处理。以上就是实现动态加载的方式。