java 类加载 apk_在Android的App中动态的加载Java类

原文的地址:http://yenliangl.blogspot.com/2009/11/dynamic-loading-of-classes-in-your.html

我正在编写一个应用程序能够加载别人开发的应用插件。对于应用程序思路的实现,我首先想到的是使用 Class.forName 以及java.lang.reflective中的提供的方法。我比较倾向于使用 Class.forName(),像下面一样:

try {

Class> handler = Class.forName(handlerClassName);

Method m = handler.getDeclaredMethod(

"addMyPreferences",

Class.forName("android.content.Context"),

Class.forName("android.preference.PreferenceCategory"),

Class.forName("java.lang.String"));

m.invoke(handler.newInstance(), this, mExtraSettingsCategory, defaultValue);

} catch(ClassNotFoundException e) {

// .....

}

// other exceptions that may be thrown by reflective API.

但是经过实践发现,上面的代码会出现ClassNotFoundException的异常。我怎么办?一个比较麻烦的问题在我的脑海里闪现,我猜想是不是别的开发者也会和我遇到同样的问题,于是我就谷歌查询,发现一个文档对我理解:为什么上面的代码会抛出ClassNotFoundException异常非常有帮助(点击这里)。

该文档上说,Java的基本动态加载模块依赖于java的parent-chaild层次结构和ClassLoader类。通过日志打印出类加载的顺序(层次)对于理解类的加载很有帮助。因此,我就这么做了。

ClassLoader cl = this.getClass().getClassLoader();

while (cl != null) {

Log.d(TAG, "====> class loader: " + cl.getClass());

cl = cl.getParent();

}

在我的电脑上,在类加载的时候打印显示加载了2个类分别是 dalvik.system.PathClassLoader类 和 java.lang.BootClassLoader类。最有趣的事情是使用 PathClassLoader类。查看它的文档发现 PathClassLoader类能够接受不同类型的值作为它的构造函数的参数,直接从文档上复制过来看:

public PathClassLoader (String path, ClassLoader parent)

Creates a PathClassLoader that operates on a given list of files and directories. This method is equivalent to calling PathClassLoader(String, String, ClassLoader) with a null value for the second argument (see description there).

* Directories containing classes or resources.

* JAR/ZIP/APK files, possibly containing a "classes.dex" file.

* "classes.dex" files.

好啦,基于文档上面的规定说明,我猜测使用apk文件名构造PathClassLoader 类实例,并且这个apk应用是在传递中创建,如下:

PathClassLoader("/data/app/org.startsmall.myapp.apk",

ClassLoader.getSystemClassLoader());

因此,如果我想使用Class.forName()就应该从第三方应用开发者哪里知道要加载的类的名字,并且必须重新构造PathClassLoader 类实例从我的apk应用和第三方应用中加载类,下面是示例代码:

final String apkFiles =

"/data/app/org.startsmall.myapp.apk:" + // myself

// handlers defined by other developers

"/data/app/" + handlerClassName.substring(0, lastDotPos) + ".apk";

dalvik.system.PathClassLoader myClassLoader =

new dalvik.system.PathClassLoader(

apkFiles,

ClassLoader.getSystemClassLoader());

// ...

try {

Class> handler =

Class.forName(handlerClassName, true, classLoader);

// Call reflective APIs.

} catch (ClassNotFoundException e) {

// .....

}

经过上面这些经验和错误,我的代码终于可以加载第三方的类和方法,并且可以执行达到预期的效果。

注:翻译的不好,请无视直接看原文。

你可能感兴趣的:(java,类加载,apk)