android之Android类装载器DexClassLoader之一
转自http://www.tuicool.com/articles/FneqEjz
Android类装载器DexClassLoader的简单使用-----制作android插件的前奏 - David小硕
博客园-原创精华区 原文 http://www.cnblogs.com/dividxiaoshuo-fighting/p/3682398.html 主题 安卓开发声明:此篇文章借鉴《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 <activity2 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 @Override28 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 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 block76 e.printStackTrace();77 } 78 79 }80 81 @Override82 public void onClick(View v) {83 useDexClassLoader();84 }85 }
运行后得到的结果是:
类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。
更多相关文章
- Android(安卓)对话框【Dialog】去除白色边框代码
- Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
- android webview 自定义404错误页面!
- android插件化研究
- Android(安卓)读取U盘或SD卡中的所有.txt文件
- 面试例题6:两种方法将图像显示在View上
- gif文件导出png
- 转Android(安卓)安全攻防(一):SEAndroid的编译
- NPM 和webpack 的基础使用