Android 里程碑:“插件化技术”

Android 里程碑:“插件化技术”,第1张

什么是插件化?

通常,我们的app只有一个apk文件;而插件化是一种将app拆分为多个apk的技术,每一个apk都是app功能的一部分; App 的部分功能模块在打包时并不以传统方式打包进入 apk 文件中,而是以另一种形 式二次封装进 apk内部,或者放在网络上实时下载,在需要的时候动态对这些功能模块进行加载,称之为插件化

这些单独二次封装的功能模块 apk ,就称作「插件」,初始安装的 apk 称作「宿主」

总的来说:“插件化是组件化的更进一步推进”

插件化的用途

在学习一项新技能之前,我们首先要弄清楚它能为我们带来什么;那插件化能给我们带来什么呢?

从项目管理角度来说:

● 插件化将应用的不同功能划分到一个个的插件中,便于程序的维护

● 每个插件可以单独运行调试极大的提高了开发效率

● 每个插件互不影响,多人协同开发更加高效

从程序运行角度来说:

● 按需加载插件,占用内存更少

● 按需更新,更省流量

从公司运营角度来说:

● 实时更新,便于运营推广

● 修复线上BUG,将风险降到最低

使用插件化的好处

● 宿主和插件分开编译: 各个模块封装成不同的插件APK,不同模块可以单独编译,提高了开发效率

● 并发开发: 不同的团队负责不同的插件APP,这样分工更加明确

● 动态更新插件: 可以通过上线新的插件来解决线上的BUG,达到“热修复”的效果

● 按需下载模块

● 解决了方法数超过限制的问题

● 减小了宿主APK的体积

使用插件化所需要的理论基础

插件化像是一门十分高深的武功,它需要修习者有一定理论基础后才能修炼那它需要哪些理论支撑呢?

ClassLoader

● ClassLoader 叫做类加载器, 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流” 这个动作放到java虚拟机外部去实现,以便让应用程序自己决定去如何获取所需要的类,实现这个动作的代模块称之为“类加载器”

● ClassLoader是由JVM平台提供的类加载器,它允许程序从网络、硬盘甚至是内存加载Class,这就为Android插件化提供了最基础的技术保障

● ClassLoader负责在运行时将Java类动态加载到JVM中,而且ClassLoader是JRE的一部分。因此,由于ClassLoader的存在,JVM无需了解底层文件和文件系统即可运行Java程序

● ClassLoader并不会一次把所有Java类加载到内存中,而是在应用程序需要的时候加载。这就是ClassLoader发挥作用的地方,它们负责将类加载到内存中

反射和Hook技术

Hook动态注入代码

● Hook机制是回调机制的一种,普通的回调是静态的,我们必须提前写好回调接口;而Hook机制在Java中则可以利用反射,针对切入点(通常是一个成员变量),采用替换的手段,使代码在运行时改变

Android Hook

● 在Android *** 作系统中,有一套自己的事件分发机制,所有的代码调用和回调都是按照一定顺序执行的,Hook技术存在的意义就在于,我们可以在事件传送到终点前截获并监控该事件的传输,并且做一些自己的处理

Hook的翻译是"钩子"

● 我们知道Android *** 作系统有一套自己的机制,例如,Activity启动流程、事件分发机制、资源管理机制等;有时候,这些机制无法满足我们的需求,通过系统的API也无能为力;这时候就需要Hook技术对原有流程进行拦截,然后将系统流程替换成我们自己的流程;而反射是Hook技术的一种必要手段

APP安装过程

Android应用程序安装有四种方式,分别如下:

● 系统启动时安装,没有安装界面

● 第三方应用安装,有安装界面,也是我们最熟悉的方式

● ADB命令安装,没有安装界面

● 通过Google Play市场安装,没有安装界面

我们知道apk文件中包含了app运行需要的Activity、Service等信息;这些信息是在程序安装过程中通过PackageManagerService解析AndroidManifest文件取得的; 只有了解了这些原理,我们才能知道如何解析插件中的Activity、Service等信息

资源管理

资源,是APK包体积过大的病因之一;插件化技术将模块解耦,通过插件的形式加载; 插件化技术中,每个插件都能够作为单独的APK独立运行;宿主启动插件的类,难免要涉及插件类中的资源问题

那么,如何加载插件资源,就成为一个待解决的问题

● 在Android打包编译时,gradle会为图片、文案等资源生成一个唯一的Id。在运行期,通过对资源Id的引用来查找相应的资源;由于宿主apk和各插件apk打包不是在一次gradle assemble命令中完成的,这就有可能造成多个apk中产生的资源id相同,我们称之为资源冲突

● 各apk中的资源是无法共享的,例如在宿主中无法引用插件中的资源

为了解决这两个问题,我们有必要掌握Android平台的资源管理机制

● 单纯解析出插件的Activity、Service等信息是不行,我们期望的是这些Activity、Service等可以像我们普通App中的一样可以正常运行

● 这就需要我们去熟悉四大组件的启动流程,然后通过Hook技术加入宿主启动插件的Activity、Service等逻辑

四大组件的启动流程

四大组件支持

Android开发中有一些特殊的类,是由系统创建的,并且由系统管理生命周期,如常用的四大组件,activity,service,broadcastReceiver和contentProvider,仅仅构造出这些类的实例是没有用的,还需要管理组件的生命周期;其中以activity的最为复杂

不同的框架有不同的方式,大致分为两种方式

● ProxyActivity代理

● hook方式

hook启动插件activity需要解决两个问题:

● 插件Activity没有在Manifest文件中注册,如何绕过检测

● 如何构造Activity实例,并同步生命周期

四大组件中除了BroadcastReceiver以外,其他三种组件都必须要在AndroidManifest注册,对于它来说,它既可以在AndroidManifest由可以代码动态注册;

在调用方式上,Activity、Service、BroadcastReceiver都需要借助Intent,而ContentProvider无需借助Intent

结语

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

PS:有问题欢迎指正,可以在评论区留下你的建议和感受;

欢迎大家点赞评论,觉得内容可以的话,可以转发分享一下

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/905661.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-15
下一篇 2022-05-15

发表评论

登录后才能评论

评论列表(0条)

保存