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

Android插件化原理

类加载与双亲委托机制

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

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

资源加载

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

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

四大组件支持

在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。

两种支持Activity的方式

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

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

Android插件化方案

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

Shadow

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

全动态插件框架架构和非动态插件框架架构进行对比如下:

Android插件化原理与方案详解-LMLPHP
非动态插件框架架构

Android插件化原理与方案详解-LMLPHP
全动态插件框架架构图

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

RePlugin

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

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

AAB (Android App Bundle)

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

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

Qigsaw

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

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

Atlas

Atlas是阿里巴巴开发的一款插件化框架,它通过修改ClassLoader,实现了插件的动态加载和卸载。

优点:功能强大,支持热更新,可以动态加载和卸载插件,支持插件之间的相互调用,有丰富的文档和社区支持。
缺点:实现复杂,可能需要修改大量的代码才能实现插件化。
选择建议:如果你需要一个功能强大且有丰富的文档和社区支持的插件化框架,那么Atlas可能是一个不错的选择。

插件增量更新

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

Sophix

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

优点

支持全量更新,增量更新,热更新,支持So库修复。
提供了详细的接入文档和稳定的服务支持。
有较好的兼容性和稳定性。

缺点

只支持阿里系的应用,对外部应用支持不足。
需要接入阿里的mPaaS移动开发平台,对于一些不希望接入阿里云的项目可能会有影响。

Bugly hotfix

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

优点

提供了全面的热更新解决方案,包括热修复和热更新。
提供了详细的接入文档和稳定的服务支持。
有较好的兼容性和稳定性。

缺点

需要接入腾讯的Bugly平台,对于一些不希望接入腾讯云的项目可能会有影响。
对于一些复杂的修复场景,可能需要更深入的定制,这可能会增加接入的复杂性。

插桩热更新

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

优点

原理简单,实现相对容易。
不依赖于任何第三方平台,可以自由定制。

缺点

需要对字节码插桩技术有一定的了解,对于一些开发者来说可能会有一定的学习成本。
对于一些复杂的修复场景,可能需要更深入的定制,这可能会增加接入的复杂性。
兼容性和稳定性可能不如Sophix和Bugly hotfix。

03-08 17:48