Android类装载器DexClassLoader的简单使用-----制作android插件的前奏
声明:此篇文章借鉴《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函数。
package com.david.plugin;
import android.util.Log;
public class Plugin {
private static final String TAG=Plugin.class.getSimpleName();
public Plugin(){
Log.i(TAG, "PluginClass is initialized");
}
public int addition(int a,int b){
return a+b;
}
}
plugin的apk中AndroidManifest文件中,activity必须声明一个action。
<activity
android:name="com.david.plugin.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.david.plugin.client"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
将plugin.apk装载进Android设备中。Host.apk中主activity调用的代码如下:
package com.david.host; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List; import dalvik.system.DexClassLoader;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class MainActivity extends ActionBarActivity implements OnClickListener{ private static final String plugin_package = "com.david.plugin.client";
private PackageManager pm;
private ResolveInfo resolveInfo;
private Button btn_classLoader; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// useDexClassLoader();
btn_classLoader=(Button) findViewById(R.id.btn_classLoader);
btn_classLoader.setOnClickListener(this);
} @SuppressLint("NewApi")
public void useDexClassLoader() {
Intent classIntent = new Intent(plugin_package, null);
pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(classIntent, 0);
resolveInfo = activities.get(0);
ActivityInfo activityInfo = resolveInfo.activityInfo; String div = System.getProperty("path.separator");
String packageName = activityInfo.packageName;
String sourceDir = activityInfo.applicationInfo.sourceDir;
System.out.println(sourceDir);
String outDir = getApplicationInfo().dataDir;
System.out.println(outDir);
String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;
System.out.println(libraryDir); DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,
libraryDir, this.getClass().getClassLoader());
try {
Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");
Object instance = loadClass.newInstance();
Class[] params = new Class[2];
params[0]=Integer.TYPE;
params[1]=Integer.TYPE;
Method method = loadClass.getMethod("addition", params);
Integer result = (Integer) method.invoke(instance, 12,32);
System.out.println(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } @Override
public void onClick(View v) {
useDexClassLoader();
}
}
运行后得到的结果是:

类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。
Android类装载器DexClassLoader的简单使用-----制作android插件的前奏的更多相关文章
- Android中SharedPerforences的简单使用示例 --Android基础
SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedP ...
- Android系列:res之shape制作
大家好,pls call me francis. nice to me you. 本文将介绍使用在Android中使用shape标签绘制drawable资源图片. 下面的代码是shap标签的基本使用情 ...
- 基于Android平台的图书管理系统的制作(1)
在学习了郭神的第一行代码前半段之后,想通过一次实践来完成对已学知识的巩固.于是码下了这个图书管理系统客户端. IDE Android studio,语言 JAVA.XML: 在刚开始设计的时候对于这个 ...
- Xamarin.Android之Spinner的简单探讨
一.前言 今天用了一下Spinner这个控件,主要是结合官网的例子来用的,不过官网的是把数据写在Strings.xml中的, 某种程度上,不是很符合我们需要的,比较多的应该都是从数据库读出来,绑定上去 ...
- Xamarin.Android之封装个简单的网络请求类
一.前言 回忆到上篇 <Xamarin.Android再体验之简单的登录Demo> 做登录时,用的是GET的请求,还用的是同步, 于是现在将其简单的改写,做了个简单的封装,包含基于Http ...
- [电子书] 《Android编程入门很简单》
<Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...
- android复习第一天-----简单的android常识
前言:要去面试了,这些天花一些事件把android中简单的知识点来串联的复习一下 1,android中的工程结构 src文件夹:存储android文件的源代码 gen文件夹:有工具自动生成,不要去修改 ...
- GitHub 上排名前 100 的 Android 开源库进行简单的介绍
若有任何疑问可通过邮件或微博联系我 项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开 ...
- [原创]Android中LocationManager的简单使用,获取当前位置
Android中LocationManager的提供了一系列方法来地理位置相关的问题,包括查询上一个已知位置:注册/注销来自某个 LocationProvider的周期性的位置更新:以及注册/注销接近 ...
随机推荐
- C#整合VS2010和NUnit
软件下载 .Net单元测试工具 NUnit下载:http://www.nunit.org/index.php?p=download,最新的为NUnit-2.6.0.12051.msi,下载安装. VS ...
- go语言中通过http访问需要认证的api
func main() { //生成client 参数为默认 client := &http.Client{} //生成要访问的url url := "https://api.XXX ...
- clear(), evict(), flush()三种方法的用法实例
先贴代码: @Before public void init() { System.out.println("Test开始之前执行"); Configuration configu ...
- 关于插入date型数据
create table student (name varchar2(10) not null primary key , enrolldate date not null);//创建student ...
- Java集合set的并、交、差操作
集合的并.交.差操作 Set<Integer> result = new HashSet<Integer>(); Set<Integer> set1 = new H ...
- pyhon模块之日志模块
#Auther Bob#--*--coding:utf-8--*-- import logging #python一共有5个级别的日志,debug.info.warning.error.critica ...
- Legendre多项式
Legendre多项式 时间限制: 1 Sec 内存限制: 128 MB 题目描述 Legendre多项式的递归公式
- JAVA Get UUID
UUID是通用唯一标识码(Universally Unique Identifier),通过开源软件基金会(OSF)设立的一种算法生成.它的主要作用就是保证生成的字符串在同一时空中所有机器上都是唯一的 ...
- 《JavaScript DOM编程艺术》笔记
1. 把<script>标签放到HTML文档的最后,<body>标签之前能使浏览器更快地加载页面. 2. nodeType的常见取值 元素节点(1) 属性节点(2) 文本节点( ...
- java 事件监听
事件监听实现: 三要素: 1.事件源(数据源,要处理的数据) 2.事件 (承载数据,传递信息并被监听) 3.监听器 (负责对数据的业务处理) --该开发用例采用了Spring的事件监听 1. 定义事 ...