文档章节

Android插件化动态加载原理(三)

chunquedong
 chunquedong
发布于 2016/05/21 22:27
字数 724
阅读 547
收藏 3
点赞 2
评论 0

前面的文章介绍了动态加载apk包中的代码,本篇介绍如何启动插件中的未注册的Activity。Android系统要求所有的组件都在AndroidManifest.xml中注册。这样比较麻烦,插件中不能增加宿主中没有声明的Activity,很不灵活。要绕过Activity注册的限制也不是没有可能,主要有两种方法。

方案1 代理Activity

能想到的一种简单办法是代理模式,注册一个ProxyActivity,假设插件中未注册的Activity叫做PluginActivty。我们把PluginActivty当做普通的类,手动来维护Activity的生命周期。代码大概像这样:

class ProxyActivity extends Activity {
  Activty pluginActivity;
  @Overrride void onCreate() {
    pluginActivity = (Activity)Class.forName("com.test.PluginActivity").newInstance();
    Reflection.set(pluginActivity, "mBase", this);
    pluginActivity.onCreate();  
  }
  @Overrride void onDestroy() {
    pluginActivity.onDestroy();  
  }
  @Overrride void onTouch(Evnet e) {
    pluginActivity.onTouch(e);
  }
}

在ProxyActivity中,我们使用反射的方法初始化插件中未注册的Activity,并初始化一些属性。然后把系统告诉ProxyActivity的告诉PluginActivity。

这种代理方式有些缺点。有时候不能做到对开发者透明,要遵守一些编码约定。由于不是真正的Activity,有些特殊用法也会导致bug。所以实际上axbase插件框架使用的是第二种方案。

方案2 替换Instrumentation

另外一种方法是hook系统的Instrumentation类。Instrumentation类就像是Android系统天生为Android插件化定制的一样,恰到好处。

通过阅读Android源码ActivityThread.java可知,在每次打开新Activity时,由Instrumentation.newActivity方法负责创建Activity实例。如果我们能重写newActivity方法,我们注册一个叫ActivityStub的Activity组件,在newActivity中判断如果是要创建ActivityStub时创建一个插件的Activity返回给系统。这样达到了挂羊头卖狗肉的效果,成功的绕过了Activity需要注册的限制。代码大概像这样:

class MyInstrumentation extends Instrumentation {
  @Overrride Activity newActivity(ClassLoader cl, String className, Intent intent) {
    if (className.equals(ActivityStub.class.getName())) {
        pluginClassLoader.loadClass("com.test.PluginActivity");
        return (Activity)clazz.newInstance();
    }
    return super.newActivity(cl, className, intent);
  }
}

上面代码中的"com.test.PluginActivity"是写死的一个类名,如果要加载某个其它Activity则可以通过Intent.putExtra传递类名参数。

最后,我们再来看一下如何通过反射来替换掉系统的Instrumentation:

Context contextImpl = ((ContextWrapper) context).getBaseContext();
		Object activityThread = Reflection.getField(contextImpl, "mMainThread");
Reflection.setField(activityThread, "mInstrumentation", instrumentation);

同样是反射修改mMainThread的mInstrumentation为我们自定义的instrumentation对象。

方案3 ClassLoader欺骗

其实还有另外一种方式,就是在ClassLoader中,当请求加载ActivityStub类时,直接返回PluginActivity类,来欺骗系统。这种方式和instrumentation方法类似,只是没有Intent来传递类名参数,可能只能使用静态变量来传递。这里不再详细介绍。

其它关于插件化开发的内容在下篇介绍。 请关注axbasePlugin插件化开发框架Github

© 著作权归作者所有

共有 人打赏支持
chunquedong

chunquedong

粉丝 45
博文 127
码字总数 35560
作品 4
海淀
高级程序员
Android插件化开发,初入殿堂

好久没有写博客了,这次准备写写我这几天的研究成果——Android插件化开发框架CJFrameForAndroid。 背景交代 首先,你需要知道什么是插件化开发。就拿最常见的QQ来说,在第三个界面动态那里有...

kymjs张涛
2014/10/12
0
9
有关Android插件化的一些总结思考

最近几年移动开发业界兴起了「 插件化技术 」的旋风,各个大厂都推出了自己的插件化框架,各种开源框架都评价自身功能优越性,令人目不暇接。随着公司业务快速发展,项目增多,开发资源却有限...

技术小能手
昨天
0
0
Android插件化开发之动态加载技术学习

Android插件化开发之动态加载技术学习 为什么要插件化开发和动态加载呢?我认为原因有三点: 可以实现解耦 可以解除单个dex函数不能超过65535的限制 可以给apk瘦身,比如说360安全卫士,整个...

幸运券发放
05/18
0
0
我的Android重构之旅:插件化篇

随着项目的不断成长,即便项目采用了 MVP 或是 MVVM 这类优秀的架构,也很难跟得上迭代的脚步,当 APP 端功能越来越庞大、繁琐,人员不断加入后,牵一发而动全局的事情时常发生,后续人员如同...

codeGoogle
07/09
0
0
Android开源框架源码鉴赏:VirtualAPK

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流。 文章目录 一 Vi...

郭孝星
02/10
0
0
Android插件化原理(一)Activity插件化

相关文章 Android深入四大组件系列 Android解析AMS系列 Android解析ClassLoader系列 前言 四大组件的插件化是插件化技术的核心知识点,而Activity插件化更是重中之重,Activity插件化主要有三...

刘望舒
05/29
0
0
基于Google动态化方案的组件化演进

  国内Android动态化方案已经蓬勃发展数年之久,在React Natvie、Flutter这些跨平台方案未出现之前,类似Atlas、Replugin、DLA等Android动态化方案在业界独领风骚。在国内动态化方案也分为...

Android群英传
前天
0
0
Android动态化框架App Bundles

Android App Bundles 在今年的Google I/O大会上,Google向 Android 引入了新 App 动态化框架(即Android App Bundle,缩写为AAB),与Instant App不同,AAB是借助Split Apk完成动态加载,使用...

code_xzh
05/16
0
0
那些年Android黑科技②:欺骗的艺术

“我的能量无穷无尽,只有强大暗能量才能统治Android界。 受屎吧!!! =≡Σ((( つ•̀ω•́)つ ” -- 来自暗世界android工程师 前言: 这是黑科技系列的第二篇,是Android知识正营中较有深...

猴亮屏
2017/10/24
0
0
Android高级之十三讲-HotFix、热加载和热更新

本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 组件化与插件化:前者对功能进行拆分后,独立开发,打成一个包发布;后者对功能拆分,使用主包+分包,可以分别独立发布。...

liuzxgeek
2016/12/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

idea tomcat 远程调试

tomcat 配置 编辑文件${tomcat_home}/bin/catalina.sh,在文件开头添加如下代码。    CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7829" Idea端配......

qwfys
今天
1
0
遍历目录下的文件每250M打包一个文件

#!/usr/bin/env python # -*- utf-8 -*- # @Time : 2018/7/20 0020 下午 10:16 # @Author : 陈元 # @Email : abcmeabc@163.com # @file : tarFile.py import os import tarfile import thr......

寻爱的小草
今天
1
0
expect同步文件&expect指定host和要同步的文件&构建文件分发系统&批量远程执行命令

20.31 expect脚本同步文件 expect通过与rsync结合,可以在一台机器上把文件自动同步到多台机器上 编写脚本 [root@linux-5 ~]# cd /usr/local/sbin[root@linux-5 sbin]# vim 4.expect#!/...

影夜Linux
今天
1
0
SpringBoot | 第九章:Mybatis-plus的集成和使用

前言 本章节开始介绍数据访问方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的ORM框架是很有必要的。目前,绝大部分公司都选择MyBatis框架作为底层数...

oKong
今天
12
0
win10 上安装解压版mysql

1.效果 2. 下载MySQL 压缩版 下载地址: https://downloads.mysql.com/archives/community/ 3. 配置 3.1 将下载的文件解压到合适的位置 我最终将myql文件 放在:D:\develop\mysql 最终放的位...

Lucky_Me
今天
2
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

问题终结者
今天
2
0
expect脚本同步文件expect脚本指定host和要同步的文件 构建文件分发系统批量远程执行命令

expect脚本同步文件 在一台机器上把文件同步到多台机器上 自动同步文件 vim 4.expect [root@yong-01 sbin]# vim 4.expect#!/usr/bin/expectset passwd "20655739"spawn rsync -av ro...

lyy549745
今天
1
0
36.rsync下 日志 screen

10.32/10.33 rsync通过服务同步 10.34 linux系统日志 10.35 screen工具 10.32/10.33 rsync通过服务同步: rsync还可以通过服务的方式同步。那需要开启一个服务,他的架构是cs架构,客户端服务...

王鑫linux
今天
1
0
matplotlib 保存图片时的参数

简单绘图 import matplotlib.pyplot as pltplt.plot(range(10)) 保存为csv格式,放大后依然很清晰 plt.savefig('t1.svg') 普通保存放大后会有点模糊文件大小20多k plt.savefig('t5.p...

阿豪boy
今天
3
0
java 8 复合Lambda 表达式

comparator 比较器复合 //排序Comparator.comparing(Apple::getWeight);List<Apple> list = Stream.of(new Apple(1, "a"), new Apple(2, "b"), new Apple(3, "c")) .collect(......

Canaan_
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部