Android动态加载技术初探

一、前言:

现在,已经有实力强大的公司用这个技术开发应用了,比如淘宝,大众点评,百度地图等,之所以采用这个技术,实际上,就是方便更新功能,当然,前提是新旧功能的接口一致,不然会报Not Found等错。

二、原理:

2.1 JAR文件:

Android使用动态加载的方法,和Java加载类似,都是加载.jar文件来实现,只不过,不同的是,这两者的虚拟机不同,导致.jar的格式也不同。

Android只认识.dex格式的.class文件,因为,需要做的是:

1. 正常的方法Export出一个.jar文件;

2. 使用命令将.jar转成.dex格式的.jar文件;

命令: dx --dex --output=[path]/[dest].jar [path]/[src].jar

2.2 ClassLoader:

Android系统提供了两种ClassLoader:

1. DexClassLoader

这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点。

2. PathClassLoader

只能加载已经安装到Android系统中的apk文件。

三、实战:

3.1 创建一个Jar的空工程(这里我取名叫:DynamicLoaderLib)

1. 新建两个.java文件,一个是IDynamicLoader.java(接口类),一个是LibDexJar.java(接口的实现类)

Android动态加载技术初探

2. 代码

IDynamicLoader.java

package com.chris.dynamic.loader;

public interface IDynamicLoader {
public String getHelloWorld();
}

LibDexJar.java

package com.chris.dynamic.loader;

public class LibDexJar implements IDynamicLoader {
@Override
public String getHelloWorld() {
return "HelloWorld! (使用动态加载方法)";
}
}

3. 导出jar包 (Export -> jar文件)

Android动态加载技术初探

然后点"完成"就行了(千万不要将接口定义类也打包进去,否则在运行时会报错,只打包接口实现类就行)。

大家可以随意存放,不过,为了方便维护,我在当前这个工程下面建了一个jar目录来存放。

然后,打开命令行,输入命令:

dx --dex --output=[全路径]/dst.jar [全路径]/src.jar

Android动态加载技术初探

注:大家需要把Android SDK的路径添加到系统的环境变量中,这样才能让系统找到dx工具,否则系统会报找不到。

Android动态加载技术初探

这样,就生成好了我们所需要的dex格式.class的jar包,然后把这个放到手机的/mnt/sdcard目录下(因为这个目录是可读写的)。

3.2 创建一个Test工程(DynamicLoaderTest)

Android动态加载技术初探

IDynamicLoader.java就是上一个JAR工程中的接口定义类,这里只给出MainActivity.java的实现:

         @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button dloader = (Button) findViewById(R.id.dload_jar);
dloader.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
File dexJar = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
File.separator + "LibDexJar.jar");
if(dexJar.exists()){
DexClassLoader dcl = new DexClassLoader(dexJar.getAbsolutePath(),
Environment.getExternalStorageDirectory().toString(),
null, getClassLoader());
try {
Class dloaderClass = dcl.loadClass("com.chris.dynamic.loader.LibDexJar");
IDynamicLoader IDloader = (IDynamicLoader) dloaderClass.newInstance();
Toast.makeText(MainActivity.this, "Android动态加载Demo:" + IDloader.getHelloWorld(), Toast.LENGTH_SHORT).show();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
});
}

这里可以分为4步:

1. 判断是否存在LibDexJar.jar文件在sdcard目录下;

2. 使用DexClassLoader加载JAR文件;

3. 载入Class;

4. 获取接口类的实例;

然后,就可以使用接口类中开放的接口了。

附上我运行的截图:

Android动态加载技术初探  Android动态加载技术初探

Android动态加载技术初探

最后,附上我的两个工程的源码供大家下载参考:

http://download.csdn.net/detail/qingye_love/6386981

大家多在本文章中来讨论,多多交流,谢谢!

另附上将导致的jar生成dex的jar(在代码的JAR目录下,这里我也贴出来):

dexjar.bat

@echo off
rem 使用前请先设置自己的Android SDK路径
set ANDROID_SDK="E:\chris\Android_Dev\Android\android-sdk" set path=%path%;%ANDROID_SDK%\platform-tools; rem 设置jar所存放的路径
set JAR_ROOT="E:\chris\Android_Dev\eclipse\workspace\DynamicLoaderLib\jar" rem 编译
@echo on
dx --dex --output=%JAR_ROOT%\LibDexJar.jar %JAR_ROOT%\dynamic.jar
上一篇:hiho 第1周 最长回文子串


下一篇:Nodejs 中将html转换成pdf文件