Android插件化原理与方案详解

Android插件化是一种开发模式,它允许我们动态地加载和卸载APK,从而实现模块化开发,热更新等功能。本文将详细介绍Android插件化的原理,以及几种主流的Android插件化方案。

一、Android插件化原理

1.1 类加载与双亲委托机制

Android插件化的核心原理是基于Java的类加载机制。在Java中,ClassLoader负责加载类。每个ClassLoader都有一个父ClassLoader,当我们尝试加载一个类时,ClassLoader会首先尝试让它的父ClassLoader加载这个类,这就是所谓的双亲委托机制。这种机制可以确保同一个类只会被加载一次。

在Android插件化中,我们可以创建一个新的ClassLoader来加载插件中的类。这个ClassLoader的父ClassLoader是宿主应用的ClassLoader,因此,插件中的类可以访问宿主应用中的类,但是宿主应用中的类不能访问插件中的类。

1.2 资源加载

在Android中,资源文件是通过Resources对象来加载的。每个APK都有一个独立的Resources对象,用于加载它自己的资源文件。

在Android插件化中,我们可以创建一个新的Resources对象来加载插件中的资源文件。这个Resources对象的AssetManager是通过反射创建的,可以加载任意路径的APK文件。

1.3 四大组件支持

在Android插件化中,四大组件(Activity,Service,BroadcastReceiver,ContentProvider)的支持是一个重要的问题。因为在Android系统中,这些组件都需要在AndroidManifest.xml中进行声明,而插件APK的AndroidManifest.xml是不会被解析的,所以我们需要采取一些特殊的手段来支持这些组件。

Activity:Activity是最常用的组件,也是最需要支持的组件。在插件化中,我们可以通过Proxy Activity代理或者Hook方式来支持Activity。

Service:Service的支持也是通过代理或者Hook方式来实现的。我们可以在宿主中预先声明一些代理Service,然后在运行时将这些代理Service替换为插件中的Service。

BroadcastReceiver:BroadcastReceiver的支持相对比较简单,我们可以在运行时动态注册BroadcastReceiver,或者通过Hook方式来支持静态注册的BroadcastReceiver。

ContentProvider:ContentProvider的支持是最复杂的,因为ContentProvider在应用启动时就会被创建,而且每个ContentProvider都需要一个唯一的authority。我们可以通过Hook方式来支持ContentProvider,或者使用一些特殊的技巧,例如使用同一个authority来支持多个ContentProvider。

1.4 两种支持Activity的方式

所有的插件框架在解决的问题都不是如何动态加载类,而是动态加载的Activity没有在AndroidManifest中注册,该如何能正常运行。如果Android系统没有AndroidManifest的限制,那么所有插件框架都没有存在的必要了。因为Java语言本身就支持动态更新实现的能力。

  1. Proxy Activity代理:这种方式是通过在宿主应用中预先声明一些代理Activity,然后在运行时将这些代理Activity替换为插件中的Activity。这种方式的优点是实现简单,但是有一些限制,例如无法支持插件中的Activity在AndroidManifest.xml中声明的一些属性。

  2. Hook方式:这种方式是通过Hook AMS(Activity Manager Service),替换AMS中的一些方法,从而绕过AMS的检查。这种方式的优点是可以完全支持插件中的Activity,但是实现复杂,需要对Android系统有深入的了解。

二、Android插件化方案

目前,市面上有几种主流的Android插件化方案,包括Shadow,RePlugin,AAB(Android App Bundle),Qigsaw,以及Atlas。

2.1 Shadow

2.1.1 Shadow简介

Shadow是腾讯开发的一款插件化框架,其设计目标是不修改APK文件的情况下实现插件化。Shadow通过创建一个新的ClassLoader来加载插件,从而实现插件的动态加载和卸载。

  • Shadow所指的插件是插件的代码完全是一个正常可安装的App代码,无需引用任何Shadow的库。这样的App代码应用了Shadow之后可以免安装运行在另一个App中。
  • Shadow是一个完全无Hack,甚至零反射实现的Android插件框架。
  • Shadow是一个全动态实现的插件框架,就是说插件框架的代码跟插件的代码一样都是动态发布的。

2.1.2 全动态插件框架架构和非动态插件框架架构

那么什么是全动态插件框架架构?我们和非动态插件框架架构进行对比看看。

  1. 非动态插件框架架构
  1. 全动态插件框架架构图

2.1.3 Shadow主要模块划分

graph LR A[宿主应用] -->|包含| B[基础接口] A -->|注册| C[壳子代理组件] A -->|集成| D[插件管理器] D -->|管理| E[插件包] E -->|包含| F[加载器] E -->|包含| G[运行时] E -->|包含| H[业务App] D -->|通过Binder控制| F F -->|加载| H G -->|支持| H

宿主应用

宿主应用是Shadow框架的基础载体,仅包含最小化的核心组件:

  • 基础接口定义
  • 壳子代理组件(在Manifest中注册)
  • 插件管理器的动态升级逻辑 代码量控制在约15KB,保持轻量化设计。

插件管理器(Manager)

插件管理器负责插件的完整生命周期管理:

  • 插件的下载与安装
  • Loading态的动态视图展示
  • 通过Binder通信机制控制加载器
  • 管理多版本loader实例的运行

核心运行时模块

核心运行时模块作为插件的一部分可动态升级,包含两个子模块:

1. 加载器(Loader)

  • 实现业务App的动态加载
  • 通过Binder接口接收管理器指令
  • 支持多实例运行,避免native库冲突
  • 可包含针对业务的特殊处理逻辑

2. 运行时(Runtime)

  • 提供插件运行的基础环境
  • 与业务App同版本编译
  • 确保插件与宿主的解耦运行

2.1.4 小结

  • 优点:不修改APK,插件之间完全隔离,动态加载和卸载插件,对Android API的支持非常全面。
  • 缺点:实现复杂,文档相对较少,可能会遇到一些特殊的问题,需要进行更多的测试来确保稳定性。
  • 选择建议:如果需要一个强大且灵活的插件化框架,并且不介意耗费更多的时间来理解和使用,那么Shadow可能是一个不错的选择。

2.2 RePlugin

RePlugin是360公司开发的一款插件化框架,它通过修改ClassLoader,实现了插件的动态加载和卸载。

  • 优点:插件化和组件化并行,无需修改已有代码,插件间通信机制完善。
  • 缺点:需要对插件进行特殊的打包处理,对于一些复杂的场景,可能需要进行较大的改动,对新的Android版本的支持可能会有延迟。
  • 选择建议:如果需要一个稳定且成熟的插件化框架,并且希望能够快速地进行插件化开发,那么建议选择RePlugin。

2.3 AAB (Android App Bundle)

AAB是Google官方提供的一种新的应用发布格式,它允许将应用的功能模块化,并在需要时动态地下载和安装这些模块。

  • 优点:Google官方支持,与Android系统和Google Play商店的集成度高,可以实现按需下载和安装模块。
  • 缺点:只支持Android 5.0及以上版本的设备,需要通过Google Play商店进行模块的下载和安装。
  • 选择建议:如果应用主要针对的是有Google Play服务的设备或地区,并且希望能够减小应用的初始下载大小,那么建议选择AAB。

2.4 Qigsaw

Qigsaw是爱奇艺开发的一款插件化框架,它通过修改ClassLoader,实现了插件的动态加载和卸载。

  • 优点:支持动态加载和卸载插件,支持热更新,支持分包。
  • 缺点:实现相对复杂,需要对插件进行特殊的打包处理,对新的Android版本的支持可能会有延迟。
  • 选择建议:如果需要一个支持热更新和分包的插件化框架,并且愿意耗费更多的时间来理解和使用,那么建议选择Qigsaw。

2.5 Atlas

Atlas是阿里巴巴开发的一款插件化框架,它通过修改ClassLoader,实现了插件的动态加载和卸载。官方的介绍文章可以阅读Atlas-手淘组件化框架的前世今生和未来的路

  • 优点:功能强大,支持热更新,可以动态加载和卸载插件,支持插件之间的相互调用,有丰富的文档和社区支持。
  • 缺点:实现复杂,可能需要修改大量的代码才能实现插件化。
  • 选择建议:目前Atlas开源项目处于没有维护的状态,只能作为技术方案参考。

三、插件增量更新

插件维护阶段,大的需求变更较少,很多时候更新插件版本只是为了解决一些用户反馈的小问题。但即使是很小的更新,都需要插件发布新版本,用户更新-下载-安装这些步骤中,都会造成用户的流失。那有没有可能对插件进行热更新呢?只需要下发小的补丁文件即可以达到修复的能力确实更适合我们业务场景。目前比较流行的热更新方案有下面这些。

3.1 Sophix

Sophix是阿里巴巴推出的一款热修复方案。Sophix的基本原理是通过AndFix实现的,AndFix是一种在Android Dalvik/ART环境下的热补丁框架,它可以在不需要重启APP的情况下动态修复Class。

  • 优点
    • 支持全量更新,增量更新,热更新,支持So库修复。
    • 提供了详细的接入文档和稳定的服务支持。
    • 有较好的兼容性和稳定性。
  • 缺点
    • 只支持阿里系的应用,对外部应用支持不足。
    • 需要接入阿里的mPaaS移动开发平台,对于一些不希望接入阿里云的项目可能会有影响。

3.2 Bugly hotfix

Bugly hotfix是腾讯推出的一款热修复方案。Bugly hotfix的基本原理是通过dex文件替换实现的,它会在运行时替换掉有问题的dex文件,从而实现热修复。

  • 优点
    • 提供了全面的热更新解决方案,包括热修复和热更新。
    • 提供了详细的接入文档和稳定的服务支持。
    • 有较好的兼容性和稳定性。
  • 缺点
    • 需要接入腾讯的Bugly平台,对于一些不希望接入腾讯云的项目可能会有影响。
    • 对于一些复杂的修复场景,可能需要更深入的定制,这可能会增加接入的复杂性。

3.3 插桩热更新

插桩热更新是一种基于字节码插桩技术的热更新方案。插桩热更新的基本原理是在编译阶段修改字节码,为方法调用插入额外的逻辑,从而实现在运行时替换方法的功能。

  • 优点
    • 原理简单,实现相对容易。
    • 不依赖于任何第三方平台,可以自由定制。
  • 缺点
    • 需要对字节码插桩技术有一定的了解,对于一些开发者来说可能会有一定的学习成本。
    • 对于一些复杂的修复场景,可能需要更深入的定制,这可能会增加接入的复杂性。
    • 兼容性和稳定性可能不如Sophix和Bugly hotfix。

四、总结

在原理部分,本文解释了类加载器的作用和插件化的基本原理,这为理解后续的插件化方案打下了基础。

在插件化方案部分,本文介绍了Shadow、RePlugin、AAB、Qigsaw和Atlas这五种主流的插件化方案。每种方案都有其独特的优点和适用场景,例如Shadow的全动态实现、RePlugin的稳定性和成熟度、AAB的官方支持和与Google Play的集成度、Qigsaw的热更新和分包支持,以及Atlas的功能强大和丰富的文档支持。

在插件增量更新部分,本文介绍了Sophix、Bugly hotfix和插桩热更新这三种热更新方案。这些方案可以在不需要用户重新下载和安装应用的情况下修复问题,大大提高了用户体验。

总的来说,在实际应用中,我们需要根据自己的具体需求和项目情况,综合考虑各种因素,选择最适合的方案。

相关推荐
惟恋惜9 小时前
Jetpack Compose 界面元素状态(UI Element State)详解
android·ui·android jetpack
_李小白9 小时前
【Android FrameWork】延伸阅读:IGraphicBufferProducer驱动UI绘制过程
android·ui
_李小白11 小时前
【Android FrameWork】第二十八天:Activity 的 UI 绘制全过程
android·ui
_李小白11 小时前
【Android FrameWork】第三十天:Surface创建流程解析
android
元亓亓亓11 小时前
考研408--操作系统--day8--操作系统--虚拟内存&请求分页&页面置换/分配
android·java·开发语言·虚拟内存
有位神秘人12 小时前
Android的Compose系列之文本TextView
android
Engineer-Jsp12 小时前
Flutter 开发 Android 原生开发神器 flutter_api_stub
android·flutter
惟恋惜12 小时前
Jetpack Compose 多页面架构实战:从 Splash 到底部导航,每个 Tab 拥有独立 ViewModel
android·ui·架构·android jetpack