DexClassLoader简单用法

设有2个类:

public class PluginClass {
public PluginClass() {
System.out.println("client initial!");
}

public int function1(int a,int b){
return a + b;
}

}

PluginClass类,定义函数 function1 , 安装到Android设备上,在建另一个工程,执行如下方法:

public void useDexClassLoader() {
Intent intent = new Intent("com.haiii.android.plugin.client", null);
PackageManager pm = getPackageManager();
final List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);
ResolveInfo rinfo = plugins.get(0);
ActivityInfo ainfo = rinfo.activityInfo;
String div = System.getProperty("path.separator");
String packageName = ainfo.packageName;
String dexPath = ainfo.applicationInfo.sourceDir;
String dexOutputDir = getApplicationInfo().dataDir;
String libPath = ainfo.applicationInfo.nativeLibraryDir;
DexClassLoader cl = new DexClassLoader(dexPath, dexOutputDir, libPath,
this.getClass().getClassLoader());
try {
Class<?> clazz = cl.loadClass(packageName + ".PluginClass");
Object obj = clazz.newInstance();
Class[] params = new Class[2];
params[0] = Integer.TYPE;
params[1] = Integer.TYPE;
Method action = clazz.getMethod("functionl" + params);
Integer ret = (Integer) action.invoke(obj, 12, 34);
Log.i("Host", "returnvalueis" + ret);
} finally {
}
}

DexClassLoader构造函数的参数意义如下:

•   dexPath,指目标类所在的A P K 或 Jar文件的路径。类装载器将从该路径中寻找指定的目标类,该路径必须是A P K 或 Ja r的全路径,比如/ data/ app/ com.haiii.android.plugin.apk。如果要包含多个路径,路径之间必须使用特定分隔符进行分隔,这个特定分隔符可使用 System.getProperty( “ path.separtor” ) 获 得 。


•   dexOutputDir,由 于 dex文件被包含在A P K 或 者 J a r 文件中,因此在装载目标类之前需要先从A P K 或 Jar文件中解压出dex文件,该参数就是指定解压出的dex文件存放路径。在 Android系统中,一个应用程序一般对应一个L inux 用户 id ,应用程序仅对属于自己的数据目录路径有写的权限,因此,该参数可以使用该程序的数据路径,本例中,该路径具体是 / data / data/ com.haiii.android.pluginhost。

•   lib P a th ,指目标类中所使用的C / C ++ 库存放的路径。


• 最后一个参数是指该装载器的父装载器,一般为当前执行类的装载器。创建了  DexClassLoader对象后,接下来就可以调用loadClaSS ()装载指定的类了,该函数返回的是一个 Class对象,注意区分Class对象和目标类PluginClass对象。 Class对象是 ClassLoader所能识别的类, 而 PluginClass是程序执行后所能识别的类,此时仅仅装载了  PluginClass的程序代码,却还没有创建出 PluginClass对象,因此接下来调用Class对象的 newlnstance ( )方法。该方法内部会调用PluginClass的构 造函数,并返回一个真正的PluginClass对象。

尽管返回的是一个PluginClass对象,但 是 Host本地却没有任何PluginClass的定义,因此不能直接去调用 PluginClass对象的任何方法,而只能使用通用的反射机制去调用PluginClass中的方法。反射机制调用时主要使用了  Method类, Class对象的 getMethod ( ) 方法可以返回该类中的任何方法, 比如本例中的名称为fu n c tio n l的方法。getMethod( ) 函数有两个参数,第一个是需要访问的函数名称, 后面一个参数是该函数参数的类型。
得到目标类的函数对象的Method后,就可以调用该Method对象的 invoke ( ) 方法。该方法的第一个参数是指执行目标函数的对象,此处该对象就应该是真正的PluginClass对象,该对象是调用Class类的newlnstance( ) 创建的。
以上代码执行后,Log输出为:


0 5 - 1 4  1 9 : 2 4 : 3 9 . 96 1 :   I N F 〇/ P l u g i n ( 7 0 4 ) :   P l u g i n C l a s s   c l i e n t   i n i t i a l i z e d
0 5 - 1 4  1 9 : 2 4 : 5 3 . 7 5 1 :   I N F O / H o s t (704) :   r e t u r n   v a l u e   is  4 6


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值