Android 使用DexClassLoader来运行其他apk中的方法

316 篇文章 5 订阅
123 篇文章 1 订阅


Android中apk文件里的dex文件是对java编译出来的.class文件进行重新打包,当然在打包之前会利用自己的协议做一些数据处理,例如优化函数表和变量表。在java程序中是使用classloader来加载这些编译生成的.class文件,然而在android程序中是通过DexClassLoader来装载这些文件的.这里我们就可以通过DexClassLoader在程序A里面动态装载程序B中的类,并且来调用B程序中的方法.


     1.首先先建立一个普通的Android工程,在这个工程中定义一个叫做plugin的类,类中实现一个简单的方法,如下所示:

[java]  view plain  copy
  1. public class PluginClass {  
  2.     private static String TAG = PluginClass.class.getSimpleName();  
  3.     public PluginClass(){  
  4.         Log.i(TAG, "initialized");  
  5.     }  
  6.     public void invoke(String s){  
  7.         Log.i(TAG, s);  
  8.     }  
      2.将这个Android工程运行到安卓设备当中去

      3.再重新建立一个Android工程,其中定义一个叫做host的类,在这个类中实现DexClassLoader动态加载第一个工程中的plugin类,如下所示:

[java]  view plain  copy
  1. public class HostClass {  
  2.     private static String TAG = HostClass.class.getSimpleName();  
  3.     private Context mContext = null;  
  4.     public HostClass(Context contect){  
  5.         mContext = contect;  
  6.     }  
  7.     public void useDexClassLoader(){  
  8.         Intent intent = new Intent();  
  9.         intent.setPackage("com.example.plugin");  
  10.         PackageManager pm = mContext.getPackageManager();  
  11.         final List<ResolveInfo> plugins = pm.queryIntentActivities(intent,0);  
  12.         if(plugins.size() <= 0){  
  13.             Log.i(TAG, "resolve info size is:" + plugins.size());  
  14.             return;  
  15.         }  
  16.         ResolveInfo resolveInfo = plugins.get(0);  
  17.         ActivityInfo activityInfo = resolveInfo.activityInfo;  
  18.           
  19.         String div = System.getProperty("path.separator");  
  20.         String packageName = activityInfo.packageName;  
  21.         String dexPath = activityInfo.applicationInfo.sourceDir;  
  22.         //目标类所在的apk或者jar的路径,class loader会通过这个路径来加载目标类文件  
  23.         String dexOutputDir = mContext.getApplicationInfo().dataDir;  
  24.         //由于dex文件是包含在apk或者jar文件中的,所以在加载class之前就需要先将dex文件解压出来,dexOutputDir为解压路径  
  25.         String libPath = activityInfo.applicationInfo.nativeLibraryDir;  
  26.         //目标类可能使用的c或者c++的库文件的存放路径  
  27.           
  28.         Log.i(TAG, "div:" + div + "   " +   
  29.                     "packageName:" + packageName + "   " +  
  30.                     "dexPath:" + dexPath + "   " +  
  31.                     "dexOutputDir:" + dexOutputDir + "   " +  
  32.                     "libPath:" + libPath);  
  33.           
  34.         DexClassLoader dcLoader = new DexClassLoader(dexPath,dexOutputDir,libPath,this.getClass().getClassLoader());  
  35.         try {  
  36.             Class<?> clazz = dcLoader.loadClass(packageName + ".PluginClass");  
  37.             Object obj = clazz.newInstance();  
  38.             Class[] param = new Class[1];  
  39.             param[0] = String.class;  
  40.             Method action = clazz.getMethod("invoke", param);  
  41.             action.invoke(obj, "test this function");  
  42.         } catch (ClassNotFoundException e) {  
  43.             Log.i(TAG, "ClassNotFoundException");  
  44.         } catch (InstantiationException e) {  
  45.             Log.i(TAG, "InstantiationException");  
  46.         } catch (IllegalAccessException e) {  
  47.             Log.i(TAG, "IllegalAccessException");  
  48.         } catch (NoSuchMethodException e) {  
  49.             Log.i(TAG, "NoSuchMethodException");  
  50.         } catch (IllegalArgumentException e) {  
  51.             Log.i(TAG, "IllegalArgumentException");  
  52.         } catch (InvocationTargetException e) {  
  53.             Log.i(TAG, "InvocationTargetException");  
  54.         }  
  55.     }  
    4.运行第二个工程之后查看log就会发现host通过DexClassLoader加载了pluginclass类,并成功调用了plugin中的方法
[plain]  view plain  copy
  1. packageName:com.example.plugin   dexPath:/data/app/com.example.plugin-1.apk   dexOutputDir:/data/data/com.example.host   libPath:/data/app-lib/com.example.plugin-1  
  2. D/dalvikvm( 8341): DexOpt: --- BEGIN 'com.example.plugin-1.apk' (bootstrap=0) ---  
  3. D/dalvikvm( 8341): DexOpt: --- END 'com.example.plugin-1.apk' (success) ---  
  4. D/dalvikvm( 8341): DEX prep '/data/app/com.example.plugin-1.apk': unzip in 39ms, rewrite 723ms  
  5. I/PluginClass( 8341): initialized  
  6. I/PluginClass( 8341): test this function  
  7. D/libEGL  ( 8341): loaded /system/lib/egl/libEGL_mali.so  
  8. D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv1_CM_mali.so  
  9. D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv2_mali.so  
  10. D/OpenGLRenderer( 8341): Enabling debug mode 0  
  11. I/HostClass( 8341): div::   packageName:com.example.plugin   dexPath:/data/app/com.example.plugin-1.apk   dexOutputDir:/data/data/com.example.host   libPath:/data/app-lib/com.example.plugin-1  
  12. I/PluginClass( 8341): initialized  
  13. I/PluginClass( 8341): test this function


转自:http://blog.csdn.net/l2show/article/details/40619585





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值