DexClassLoader 实现 Android 插件加载

标签: Android Java dev | 发表时间:2015-04-19 04:00 | 作者:
出处:http://RincLiu.com/

Java 中的 ClassLoader:

Java 中 ClassLoader 用于动态加载 Class 到 JVM,包含 BootstrapClassLoader(C++ 编写,用于加载系统核心类)、 ExtClassLoader(用于加载 lib/ext/ 目录的扩展 API)、 AppClassLoader(加载 CLASSPATH 目录下的类)。

双亲委托机制:

  • 任何自定义 ClassLoader 都必须继承 ClassLoader 抽象类,并指定其 parent 加载器,默认为 BootstrapClassLoader;

  • 任何自定义 ClassLoader 在加载一个类之前都会先委托其 parent 去加载,只有 parent 加载失败才会自己加载;

    • 这样既可以防止重复加载,又可以排除安全隐患(防止用户替换系统核心类);

    • 所以一般只需要重写 findClass()方法即可(在 parent 加载失败时调用);

  • 双亲委托机制是在 loadClass() 方法实现的,要想避开(自己验证安全性,比如 Tomcat 的 WebAppClassLoader),必须重写 loadClass() 方法;

自定义 ClassLoader 用途:

  • 在执行非置信代码前先做签名认证等;

  • 从网络、数据库等动态加载类;

类的卸载:

  • 只有当类的实例被回收,才会被 unload,但被 BootstrapClassLoader 加载的系统类除外;

  • 重复加载类会报异常,只能重新定义新的 ClassLoader 再次加载;

Dalvik 的 ClassLoader:

  • Android 里 ClassLoaderdefineClass() 方法直接抛出 UnsupportedOperationException 异常,必须借助 DexClassLoaderPathClassLoader

  • DexClassLoaderPathClassLoader 都遵循双亲委托机制,因为只重写了 findClass() 方法,没有重写 loadClass() 方法;

  • Dalvik 虚拟机识别的是 DexFile 而不是 JarFile;且 DexFile.loadClass() 方法必须通过类加载器调用,否则无效;

利用 DexClassLoader 实现 Android 插件加载:

比如我们在主应用 HostApp 中需要调用 视频插件 VideoPlayerPlugin 中的 playVideo() 方法。

给插件加入 Intent 标识:

HostApp 要查询插件信息,只能通过 PackageManager。这里我首先想到的是直接通过其 getPackageInfo() 方法。但是试想,可能插件有很多个,而且包名不同。所以最好还是通过在插件中定义空的 Activity 并加入 Intent 标识,然后调用 queryIntentActivities() 方法去查询插件信息:

1     
2
3
4
5
<activity android:name=".plugin">     
<intent-filter>
<action android:name="com.rincliu.videoplayerplugin"/>
</intent-filter>
</activity>

查询插件信息:

首先使用 PackageMananer 查询到插件的 packageNameApplicationInfo:

1     
2
3
4
5
Intent intent = new Intent("com.rincliu.videoplayerplugin");     
List<ResolveInfo> plugins = getPackageManager().queryIntentActivities(intent, 0);
ActivityInfo act = plugins.get(0).activityInfo;
String packageName = act.packageName;
ApplicationInfo app = act.applicationInfo;

上面是直接读取的第一条信息( plugins 要先判空),如果有很多种插件,或者有好几个版本,这样就需要继续读取插件的版本号等配置信息作进一步区分:

1     
2
3
Resources res = pm.getResourcesForApplication(packageName);     
int resId = res.getIdentifier("version", "string", packageName);
String version = res.getString(resId);

使用 DexClassLoader 调用插件

创建 DexClassLoader 对象:

1     
2
3
4
5
String dexSourceDir = app.sourceDir;     
String dexOutputDir = getApplicationInfo().dataDir;
String dexLibDir = app.nativeLibraryDir;
ClassLoader parentLoader = this.getClass().getClassLoader();
DexClassLoader loader = new DexClassLoader(dexSourceDir, dexOutputDir, dexLibDir, parentLoader);

使用反射调用插件中的方法:

1     
2
3
4
5
6
7
8
9
10
11
12
try {     
Class<?> clazz = loader.loadClass(packageName + ".VideoPlayerPlugin");

//Object obj = clazz.newInstance();
Constructor<?> localConstructor = clazz.getConstructor();
Object obj = localConstructor.newInstance();

//Method method = ((Class<?>) obj).getMethod("play", String.class);
Method method = clazz.getDeclaredMethod("play", String.class);

method.invoke(obj, "/sdcard/demo.mp4");
} catch (Exception e) {}

完整代码

相关 [dexclassloader android 插件] 推荐:

DexClassLoader 实现 Android 插件加载

- - RincLiu.com
Java 中的 ClassLoader:. Java 中 ClassLoader 用于动态加载 Class 到 JVM,包含. BootstrapClassLoader(C++ 编写,用于加载系统核心类)、 ExtClassLoader(用于加载 lib/ext/ 目录的扩展 API)、 AppClassLoader(加载 CLASSPATH 目录下的类).

基于PhoneGap2.9框架的android插件的实现

- - CSDN博客移动开发推荐文章
       PhoneGap平台提供了插件功能,开发者可以将重量级的功能封装在原生代码开发的插件中,并将接口暴露给JavaScript,JavaScript调用插件功能即可完成与本地代码的交互. 开发一个简单的android插件主要分以下几步:. (1)编写JAVA类,继承CordovaPlugin类,如下:.

基于插件开发的Android实现流程

- - CSDN博客推荐文章
转载请注明地址:http://blog.csdn.net/droyon/article/details/20951797. 本文记述“柯元旦”Android内核剖析中基于类装载器的“插件”架构. 1、插件不能独立运行,而必须运行于一个宿主程序中,即由宿主程序去调用插件程序. 3、宿主程序中可以管理不同的插件,包括查看插件的数目,禁用或者使用某个插件.

Android插件化方案 RePlugin/README_CN.md at dev · Qihoo360/RePlugin · GitHub

- -
RePlugin —— 历经三年多考验,数亿设备使用的,稳定占坑类插件化方案. RePlugin是一套完整的、稳定的、适合全面使用的,占坑类插件化方案,由360手机卫士的RePlugin Team研发,也是业内首个提出”全面插件化“(全面特性、全面兼容、全面使用)的方案. 极其灵活:主程序无需升级(无需在Manifest中预埋组件),即可支持新增的四大组件,甚至全新的插件.

Android 使用动态加载框架DL进行插件化开发

- - CSDN博客移动开发推荐文章
如有转载,请声明出处: 时之沙:  http://blog.csdn.net/t12x3456    (来自时之沙的csdn博客).         随着应用的不断迭代,应用的体积不断增大,项目越来越臃肿,冗余增加.项目新功能的添加,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,只能紧急发布补丁版本,强制用户进行更新.结果频繁的更新,反而容易降低用户使用黏性.或者是公司业务的不断发展,同系的应用越来越多,传统方式需要通过用户量最大的主项目进行引导下载并安装..

Android插件化(一):使用改进的MultiDex动态加载assets中的apk

- - CSDN博客推荐文章
Android插件化(一):使用改进的MultiDex动态加载assets中的apk. 为了解决65535方法数超标的问题,Google推荐使用MultiDex来加载classes2.dex,classes3.dex等等,其基本思想就是在运行时动态修改ClassLoader,以达到动态加载类的目的.

jquery 插件

- - JavaScript - Web前端 - ITeye博客
 jQuery插件的开发包括两种:. 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法. jQuery的全局函数就是属于jQuery命名空间的函数,另一种是对象级别的插件开发,即给jQuery对象添加方法. 下面就两种函数的开发做详细的说明. 1 、类级别的插件开发.

Android 遥控车

- CasparZ - LinuxTOY
您确定您真的会用 Android 手机玩赛车. 16 岁的法国学生 Jonathan Rico 使用 Android 手机通过蓝牙实现了对改装玩具汽车的遥控. 操控的方式和那些标榜的智能手机游戏一样,使用重力感应,差别是这次控制的是现实世界中的遥控汽车. 收藏到 del.icio.us |.

Android免费?毛

- Ruby - FeedzShare
来自: 36氪 - FeedzShare  . 发布时间:2011年08月17日,  已有 2 人推荐. 微软CEO Steve Ballmer在预测竞争对手产品时通常口无遮拦. 比如他去年抨击Google的Android战略时,很多人都不屑一顾. 接着Android蚕食了微软的地盘,后来又开始侵犯苹果的地盘.