一.占坑

什么是占坑?为什么要占坑?

Android插件化中,从一个插件Activity跳转到不同插件的Activity的时候,是否可以能正常跳转成功?

声明Activity需要配置什么?

声明Activity是需要AndroidManifest中声明,但是插件是依赖于宿主的,插件声明了Activity,但是插件的AndroidManifest信息,是无法动态配置到宿主里面的。

那AndroidManifest在什么时候注入的?其实这个是在App安装的时候,PackageManagerService就会读取到AndroidManifest里面的配置信息并保存一份到PackageManagerService.Settings当中,那么基本无法动态的改变这份配置信息。如果以后能动态的改变Android中记录的App配置信息,那么我们就不需要占坑了。

正因为一开始就已经将配置AndroidManifest记录到PackageManagerService,里面的记录的Activity的信息,将也会保存到PackageManagerService中。我们使用startActivity的时候,ActivityManagerService将会Activity的合法信息传送到Native层作配置验证,如果无法找到跳转Activity的配置,那么将抛出异常。

插件是app运行时,动态将插件信息插入classLoader的dex列表当中。但是宿主的AndroidManifest配置是无法动态去配置修改的。那么插件中的跳转,如何越过这种困境呢?

工程师聪明的,他们提前在宿主声明一些空Activity信息到AndoridManifest当中,然后在使用startActivity后在ActivityManagerService中在跳转到Native层前将替换成员AndroidManifest的空Activity,欺骗验证,然后Native层验证过后,在传回ActivityManagerService层后替换回需要跳转的Activity的信息。这种声明空Activity信息到AndroidManifest的行为,我们就叫做占坑了。

结合上一节,hook点来看,占坑替换是需要hook掉ActivityManagerService来完成这样的操作的,但是上一节已经介绍过Replugin唯一hook点在classloader了,那么这个占坑替换又是如何完成呢?

二.Replugin 占坑处理

宿主在引入gradle-host-library的时候,就已经引入了Replugin的占坑操作了。

Replugin在库中的AndroidManifest,已经提前的声明了各种各样的Activity Service Proivder,然后BroadcastReceiver可以动态注册,所以并不需要占坑。

我们可以看到${applicationId}它将会直接引用到宿主app build.gradle中的applicationId完成。

我们可以看到这些坑位会被合并到在宿主的full的AndroidManifest.xml里面。

你拖到最后,会发现除了这些坑位外,还会有很多360的坑位添加了,这是如何做到的呢?

这里关键在于引用了replugin-host-gradle中的配置,我们在ComponentsGenerator.groovy文件,会使用Gradle命令编译时生成这些占坑声明。之后深入介绍replugin的gradle文件的时候,会给大家更加深入介绍。

二.Replugin 跳转流程

我们看一下使用Replugin封装的的跳转

很清晰的看到pluginName,相当于Android的包名来填写。

startActivity的时候,从intent中获取包名和类名,然后再调用Factory.startActivityWithNoInjectCN

然后继续使用插件管理的继续跳转函数

这里IPluginManager对参数等说明非常情况,说明是公司的技术追求还是很高的。

进入到底层的PmLocalImpl中

然后更深入添加参数

在PmInternalImpl终于可以看真正实现,这里先要判断是否插件已经下载,getPluginConfigInfo会获取是否存在手机中是否存在插件。

然后isNeedToDownLoad来启动下载。

这里就是一些基础的下载封装了。

下载时需要上锁处理,表示当前插件正在生效。ProcessLocker是自定义的进程锁。

PluginProcressMain.getPluginHost().pluginDownloaded将会下载并加载插件,我们留到下一节再介绍,这个过程。

tryLock和unlock的调用就是对进程的锁定了。

ProcessLock里面,是使用文件锁来完成上锁的,这里的进程锁,正确的来说是文件锁。

这里面创建出文件后缀为.lock的文件,作为文件锁,然后创建出FileOutputStream为输出通道,

Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。

FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。

这里的FileChannel是FileOutputStream中获取的通道的。

这里面需要释放的时候,需要释放Filelock,FileChannel, FileOutStream, File,四个对象形成的锁。

当正常安装以后,了通过获取到PluginInInfo来判断插件是否成功安装

然后再次下载中会通过onPluginNotExitsForActivtiy,来回调提示。

如果activity是动态注册的类,直接使用startActivity打开

这里面需要判断插件中有注册到注册的Activity类

这里是通过HashMap来保存类的列表

这里其他插件首先会在Entry的入口里面在init的时候调用注册的方法注册,创建出一个ProxyRePluginVar的远程插件信息。

其会创建出两个startActivity的MethodInvoker反射的类,来用于使用跳转方法。其会分发到不同的插件的RePlugin的对象

Broadcast,Provider,Service,四大组件都是通过这种反射调用的方式,来提供其他插件调用的。

回到PmInternalImpl,插件损坏或者其他原因状态异常,判读会返回跳转目标不存在

如果是大插件,会使用onLoadLargePluginForActivity的方法启动。

这里真正的启动占坑的方式来做跳转

我们看到loadPluginActivity当中,通过ActivityInfo 来保存一个Activity的信息,然后

这里判断进程和远程分配坑位。

如果有分配,立刻进入监控状态,并强制使用UI进程运行。

使用bindActivity来绑定Activity.

bindActivity当中,继续调用到PluginContainter的alloc分配

最终会调用到allocLocked分配,里面有四种规则

(1)尝试找找到一个动态注册过的。

(2)找一个新分配的

(3)重用,最老的一个

(4)挤掉最老的一个

然后通过坑位跳转

我们在plugin-lib中的插件需要依赖的库中找到

其PluginActivity是替换的Activity

但是实际上demo中并没有使用继承PluginActivity的例子。都是使用占坑逻辑来替换,并不一定要使用PluginActivity。使用PluginActivity是嵌套生命周期的方法给Repluin管理。

Replugin占坑跳转的判断是我研究插件化以来最复杂的,代码量也很大。

作者:Cang_Wang
链接:https://juejin.im/post/597fe19751882556e0331c59
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

[Android]用架构师角度看插件化(3)-Replugin 需要占坑跳转?相关推荐

  1. [Android]用架构师角度看插件化(2)-Replugin 唯一hook点

    Replugin,为何我选择要研究这个的插件呢?很大的原因是因为它的介绍中说明,他只会有一个hook点. 一.Hook hook点是什么? 我们入门Android的时候,一定会看到过这个图,但是你确定 ...

  2. [Android]用架构师角度看插件化(1)-Replugin入门剖析

    多谢一直以来的支持,组件化的内容,应该会有一段时间不再更新,一些非常关键的技术将会在我将要出版的组件化书籍中提及. 组件化模块化的开发适合于中小型企业的业务叠加,和代码重用.而插件化的开发将组件化和模 ...

  3. 从业务架构师角度看区块链为什么以及如何改变世界

    前言 区块链技术是当前炙手可热的新兴技术,关于该技术的介绍比比皆是,但是介绍往往是从技术实现的角度来阐述区块链的优势,本文是从一个业务架构师的角度,来努力说明因为区块链,这个世界将会看到的新变化,或者 ...

  4. 阿里Android高级架构师:一个牛逼的插件又双叒诞生了!

    作者:鸿洋 原文链接:https://mp.weixin.qq.com/s/GdDkzR8AvgHROUiGwYtfOg 前言 大家在写 Android 项目的时候,免不了要引入各种 Google 提 ...

  5. java定义dll文件位置,生成网站时如何设置固定的dll文件名?-Java架构师必看

    在用VS2005发布网站项目时,默认生成bin目录下的.dll文件名是随机命名的; 如果要固定生成文网络 在用VS2005发布网站项目时,默认生成bin目录下的.dll文件名是随机命名的; 如果要固定 ...

  6. Java架构师必看的10本书

    转载自 Java架构师必看的10本书 1.大型网站系统与JAVA中间件实践 本书围绕大型网站和支撑大型网站架构的Java中间件的实践展开介绍. 从分布式系统的知识切入,让读者对分布式系统有基本的了解: ...

  7. 进阶Java架构师必看书:大型架构+框架+性能优化+中间件+分布式

    进阶Java架构师必看书:大型架构+框架+性能优化+中间件+分布式 优知学院 2018-09-05 07:21:00 1.大型网站技术架构:核心原理与案例分析 本书通过梳理大型网站技术发展历程,剖析大 ...

  8. java绘制图表控件_画图控件 Chart Control -Java架构师必看

    .NET3.5中中推出了图表控件,可以同时支持Web和WinForm两种方式,由于平时很少使用,一直网络 .NET3.5中中推出了图表控件,可以同时支持Web和WinForm两种方式,由于平时很少使用 ...

  9. 成为Java高级架构师必看的15本书

    成为Java高级架构师必看的15本书 作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐 ...

最新文章

  1. javaBean为什么要实现Serializable接口?
  2. ASP.NET Core开发-使用Nancy框架
  3. 在Linux下用netstat查看网络状态、端口状态
  4. metinfov5.0.4漏洞复现
  5. 【图像分类】如何使用 mmclassification 训练自己的分类模型
  6. SpringCloud局部过滤器自定义
  7. Quartz SpringMvc Mybatis操作数据库异常
  8. 开发工具IDEA的使用
  9. LeetCode 96——不同的二叉搜索树
  10. linux新建自定义命令,Linux 创建自定义命令
  11. PPT转换PDF格式怎么转换?后悔现在才知道
  12. windows——JDK下载与安装及环境变量配置
  13. html不支持js,解决Firefox不支持Js的InnerHtml问题
  14. 金蝶K3常用数据表(整理)
  15. CTF-实验吧-安全杂项-社交网络
  16. 网络工程师(软考)心得
  17. python 复数的模_如何使用abs在python中返回复数?
  18. Excel —— 相对引用录制宏(附视频)
  19. 人工神经网络课后题答案,人工神经网络原理答案
  20. 计算机通电后 不能正常启动,我的电脑通电后不能马上启动?为什么啊?怎么办

热门文章

  1. poj 3077Rounders(模拟)
  2. mysql:Failed to read auto-increment value from storage engine
  3. 项目管理实战之团队管理 (转)
  4. 双向链表实现电话簿C++代码实现
  5. 时频分析:短时傅里叶变换实现(2)
  6. 使用 SCons 代替 Makefile 快速构建应用程序
  7. 【Python】print 不换行输出
  8. USTC English Club Note20171020(3)
  9. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170322
  10. matlab 现代信号处理,The-first-matlab-exercise 清华大学张旭东老师现代信号处理第一次matlab习题 - 下载 - 搜珍网...