有时候我们须要使用动态更新技术,简单来说就是:当我们把开发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 dexPath the list of jar/apk files containing classes and resources, delimited by File.pathSeparator, which defaults to ":" on Android optimizedDirectory directory where optimized dex files should be written; must not be null libraryPath the list of directories containing native libraries, delimited by File.pathSeparator; may be null parent the 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<?当载入了Jar包之后。我们须要运行Jar包中的方法。这个时候我们须要使用Java的反射来处理。> 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(); }
以上就是实现动态载入的方式。