zoukankan      html  css  js  c++  java
  • Android 使用DexClassLoader要执行其他apk方法

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


         1.首先先建立一个普通的Androidproject,在这个project中定义一个叫做plugin的类,类中实现一个简单的方法,例如以下所看到的:

    <span style="font-size:14px;">public class PluginClass {
    	private static String TAG = PluginClass.class.getSimpleName();
    	public PluginClass(){
    		Log.i(TAG, "initialized");
    	}
    	public void invoke(String s){
    		Log.i(TAG, s);
    	}
    }</span>
          2.将这个Androidproject执行到安卓设备其中去

          3.再又一次建立一个Androidproject,当中定义一个叫做host的类,在这个类中实现DexClassLoader动态载入第一个project中的plugin类,例如以下所看到的:

    <span style="font-size:14px;">public class HostClass {
    	private static String TAG = HostClass.class.getSimpleName();
    	private Context mContext = null;
    	public HostClass(Context contect){
    		mContext = contect;
    	}
    	public void useDexClassLoader(){
    		Intent intent = new Intent();
    		intent.setPackage("com.example.plugin");
    		PackageManager pm = mContext.getPackageManager();
    		final List<ResolveInfo> plugins = pm.queryIntentActivities(intent,0);
    		if(plugins.size() <= 0){
    			Log.i(TAG, "resolve info size is:" + plugins.size());
    			return;
    		}
    		ResolveInfo resolveInfo = plugins.get(0);
    		ActivityInfo activityInfo = resolveInfo.activityInfo;
    		
    		String div = System.getProperty("path.separator");
    		String packageName = activityInfo.packageName;
    		String dexPath = activityInfo.applicationInfo.sourceDir;
    		//目标类所在的apk或者jar的路径。class loader会通过这个路径来载入目标类文件
    		String dexOutputDir = mContext.getApplicationInfo().dataDir;
    		//因为dex文件是包括在apk或者jar文件里的,所以在载入class之前就须要先将dex文件解压出来,dexOutputDir为解压路径
    		String libPath = activityInfo.applicationInfo.nativeLibraryDir;
    		//目标类可能使用的c或者c++的库文件的存放路径
    		
    		Log.i(TAG, "div:" + div + "   " + 
    					"packageName:" + packageName + "   " +
    					"dexPath:" + dexPath + "   " +
    					"dexOutputDir:" + dexOutputDir + "   " +
    					"libPath:" + libPath);
    		
    		DexClassLoader dcLoader = new DexClassLoader(dexPath,dexOutputDir,libPath,this.getClass().getClassLoader());
    		try {
    			Class<?> clazz = dcLoader.loadClass(packageName + ".PluginClass");
    			Object obj = clazz.newInstance();
    			Class[] param = new Class[1];
    			param[0] = String.class;
    			Method action = clazz.getMethod("invoke", param);
    			action.invoke(obj, "test this function");
    		} catch (ClassNotFoundException e) {
    			Log.i(TAG, "ClassNotFoundException");
    		} catch (InstantiationException e) {
    			Log.i(TAG, "InstantiationException");
    		} catch (IllegalAccessException e) {
    			Log.i(TAG, "IllegalAccessException");
    		} catch (NoSuchMethodException e) {
    			Log.i(TAG, "NoSuchMethodException");
    		} catch (IllegalArgumentException e) {
    			Log.i(TAG, "IllegalArgumentException");
    		} catch (InvocationTargetException e) {
    			Log.i(TAG, "InvocationTargetException");
    		}
    	}
    }</span>
        4.执行第二个project之后查看log就会发现host通过DexClassLoader载入了pluginclass类,并成功调用了plugin中的方法
    <span style="font-size:14px;">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
    D/dalvikvm( 8341): DexOpt: --- BEGIN 'com.example.plugin-1.apk' (bootstrap=0) ---
    D/dalvikvm( 8341): DexOpt: --- END 'com.example.plugin-1.apk' (success) ---
    D/dalvikvm( 8341): DEX prep '/data/app/com.example.plugin-1.apk': unzip in 39ms, rewrite 723ms
    I/PluginClass( 8341): initialized
    I/PluginClass( 8341): test this function
    D/libEGL  ( 8341): loaded /system/lib/egl/libEGL_mali.so
    D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv1_CM_mali.so
    D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv2_mali.so
    D/OpenGLRenderer( 8341): Enabling debug mode 0
    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
    I/PluginClass( 8341): initialized
    I/PluginClass( 8341): test this function</span>
    


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Hudson安装配置、部署应用及分析
    利用JMeter的beanshell进行接口的加密处理
    安装loadrunner时出现”命令行选项语法错误键入命令 ?获得帮助“的解决方法
    Oracle创建表空间、创建用户以及授权
    Linux 命令行模式 你需要知道的那些事
    Form onsubmit 事件 阻止表单提交() 必须选中同意选项才可以提交
    Django中Form的Textarea字段
    css实现自适应屏幕高度;
    Django 1.10 找不到静态资源解决方法
    时间戳 JavaScript parse() 方法 处理技巧
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4613093.html
Copyright © 2011-2022 走看看