Android类装载器DexClassLoader的简单使用-----制作android插件的前奏

摘要:
标准Java SDK中有一个ClassLoader类。使用这个类,您可以加载所需的类文件。前提条件是必须为ClassLoader类初始化指定类文件的路径。ClassLoader与import正好相反,它更灵活。每个ClassLoader必须有一个父ClassLoader。加载类文件时,子ClassLoader将首先请求其父ClassLoader加载该文件。只有当父ClassLoader找不到该文件时,子ClassLoader才会继承并加载该类。

声明:此篇文章借鉴《android内核剖析》整理得来。

一、装载器简介

  “类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是

ClassLoader类初始化必须制定class文件的路径。

  import关键字引用的类文件和ClassLoader动态加载类的区别:

    import引用类的两个特点:1、必须存在于本地,当程序运行该类时,内部类装载器会自动装载该类。

                 2、编译时必须在现场,否则编译过程会因找不到引用文件而不能正常编译。

    classLoader的特点正好于import相反,而且更自由灵活。

  每一个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求其父ClassLoader加载该文件,只有当其父ClassLoader找不到该文件时,子ClassLoader才会继承装载该类。这是一种安全机制。对于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器DexClassLoader。

二、DexClassLoader的方法的实用

  假设有两个apk,第一个叫做Host,第二个叫Plugin。Plugin中第一个一个类Plugin,该类中定义了一个addition函数。

  

 1 package com.david.plugin;
 2 
 3 import android.util.Log;
 4 
 5 public class Plugin {
 6     
 7     private static final String TAG=Plugin.class.getSimpleName();
 8     
 9     public Plugin(){
10         Log.i(TAG, "PluginClass is initialized");
11     }
12     
13     public int addition(int a,int b){
14         return a+b;
15     }
16     
17 }

  plugin的apk中AndroidManifest文件中,activity必须声明一个action。

1 <activity
2             android:name="com.david.plugin.MainActivity"
3             android:label="@string/app_name" >
4             <intent-filter>
5                 <action android:name="com.david.plugin.client"/>
6                 <action android:name="android.intent.action.MAIN" />
7                 <category android:name="android.intent.category.LAUNCHER" />
8             </intent-filter>
9         </activity>

  将plugin.apk装载进Android设备中。Host.apk中主activity调用的代码如下:

 1 package com.david.host;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 import java.util.List;
 6 
 7 import dalvik.system.DexClassLoader;
 8 import android.support.v7.app.ActionBarActivity;
 9 import android.annotation.SuppressLint;
10 import android.content.Intent;
11 import android.content.pm.ActivityInfo;
12 import android.content.pm.PackageManager;
13 import android.content.pm.ResolveInfo;
14 import android.os.Bundle;
15 import android.view.View;
16 import android.view.View.OnClickListener;
17 import android.widget.Button;
18 
19 
20 public class MainActivity extends ActionBarActivity implements OnClickListener{
21 
22     private static final String plugin_package = "com.david.plugin.client";
23     private PackageManager pm;
24     private ResolveInfo resolveInfo;
25     private Button btn_classLoader;
26 
27     @Override
28     protected void onCreate(Bundle savedInstanceState) {
29         super.onCreate(savedInstanceState);
30         setContentView(R.layout.activity_main);
31 //        useDexClassLoader();
32         btn_classLoader=(Button) findViewById(R.id.btn_classLoader);
33         btn_classLoader.setOnClickListener(this);
34     }
35 
36     @SuppressLint("NewApi")
37     public void useDexClassLoader() {
38         Intent classIntent = new Intent(plugin_package, null);
39         pm = getPackageManager();
40         List<ResolveInfo> activities = pm.queryIntentActivities(classIntent, 0);
41         resolveInfo = activities.get(0);
42         ActivityInfo activityInfo = resolveInfo.activityInfo;
43 
44         String div = System.getProperty("path.separator");
45         String packageName = activityInfo.packageName;
46         String sourceDir = activityInfo.applicationInfo.sourceDir;
47         System.out.println(sourceDir);
48         String outDir = getApplicationInfo().dataDir;
49         System.out.println(outDir);
50         String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;
51         System.out.println(libraryDir);
52 
53         DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,
54                 libraryDir, this.getClass().getClassLoader());
55         try {
56             Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");
57             Object instance = loadClass.newInstance();
58             Class[] params = new Class[2];
59             params[0]=Integer.TYPE;
60             params[1]=Integer.TYPE;
61             Method method = loadClass.getMethod("addition", params);
62             Integer result = (Integer) method.invoke(instance, 12,32);
63             System.out.println(result);
64         } catch (ClassNotFoundException e) {
65             e.printStackTrace();
66         } catch (InstantiationException e) {
67             e.printStackTrace();
68         } catch (IllegalAccessException e) {
69             e.printStackTrace();
70         } catch (NoSuchMethodException e) {
71             e.printStackTrace();
72         } catch (IllegalArgumentException e) {
73             e.printStackTrace();
74         } catch (InvocationTargetException e) {
75             // TODO Auto-generated catch block
76             e.printStackTrace();
77         } 
78 
79     }
80 
81     @Override
82     public void onClick(View v) {
83         useDexClassLoader();
84     }
85 }

  运行后得到的结果是:

Android类装载器DexClassLoader的简单使用-----制作android插件的前奏第1张

类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。

免责声明:文章转载自《Android类装载器DexClassLoader的简单使用-----制作android插件的前奏》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇如何将WPF browser app 转换成WPF windows application安装 jdk-8u121( jdk1.8 ) Eclipse jee neon java EE 4.6 并配置 中国科学技术大学 http://mirrors.ustc.edu.cn/eclipse/ 仓库源下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

android项目 添加

vendor的英文单词有“提供商”的意思,在Google的Android原始代码里vendor目录包含了CPU硬件提供商的一些信息。Android系统作为开放的手持设备操作系统,在发布之初必须要提供配置接口给CPU提供商,这样Android的系统才能在不同的CPU上运行。 实际上vendor目录就是Android系统预留给我们加入定制化信息的目录。在这个目...

Android 官方AB Update说明

Android 官方AB Update说明 A/B 系统更新,也称为无缝更新,用于确保可运行的启动系统在无线 (OTA) 更新期间能够保留在磁盘上。这样可以降低更新之后设备无法启动的可能性,也就是说,用户需要将设备送到维修/保修中心进行更换和刷机的情况将有所减少。 用户在 OTA 期间可以继续使用设备。在更新过程中,仅当设备重新启动到更新后的磁盘分区时,会...

Android 的窗口管理系统 (View, Canvas, WindowManager)

http://blog.csdn.net/ritterliu/article/details/39295271 From漫天尘沙 在图解Android - Zygote 和 System Server 启动分析一 文里,我们已经知道Android 应用程序是怎么创建出来的,大概的流程是 ActivityManagerService -> Zygote...

安卓开发之activity详解(sumzom)

    app中,一个activity通常是指的一个单独的屏幕,相当于网站里面的一个网页,它是对用户可见的,它上面可以显示一些控件,并且可以监听处理用户的时间做出响应。        那么activity之间如何进行通信呢?他们是通过intent进行通信以及切换。Intent有两个重要部分(动作传递,数据传递); Ø神马是Activity?     act...

Android 2.1 源码结构分析

Android 2.1   |-- Makefile   |-- bionic (bionic C库)   |-- bootable (启动引导相关代码)   |-- build (存放系统编译规则及generic等基础开发包配置)   |-- cts (Android兼容性测试套件标准)   |-- dalvik (dalvik JAVA虚拟机)   |-...

android的armeabi和armeabi-v7a

在ANE中如果SDK调用了so库,则需要把so库放到ANE下Android-ARM/lib/armeabi (调试模式)或者 armeabi-v7a(发行模式)下。 可以贴个ADT代码说明问题:   //m_configType.equals("apk") 是否是发行模式 //(hasCaptiveRuntime() 是否带运行时 if ((m_con...