Skip to content
/ Shadow Public
forked from Tencent/Shadow

零反射全动态Android插件框架

License

Notifications You must be signed in to change notification settings

jjyw/Shadow

Repository files navigation

Shadow--零反射实现的插件框架

"零反射"显然是一个Shadow最值得强调的特点,没错,Shadow在实现将App免安装运行这件事上没有使用任何反射调用。可以说Shadow是一个完全按照Android系统说明书实现的插件框架,在这个实现中不包含任何Android官方文档上找不到的东西。因此Shadow可以稳定运行在任何版本的Android系统上,包括严格限制非公开SDK接口访问的Android9.0。再换一种说法,Shadow不会触发任何Android 9.0的限制API(包括黑名单、深灰名单、浅灰名单)。

Shadow的特点

  • 复用独立安装App的源码:插件App的源码原本就是可以正常安装运行的。
  • 完全无Hack实现:从理论上就已经确定无需对任何系统做兼容开发,更无任何隐藏API调用,和Google限制非公开SDK接口访问的策略完全不冲突。
  • 全动态实现:一次性实现完美的插件框架很难,但Shadow将这些实现全部动态化起来,使插件框架的代码成为了插件的一部分。插件的迭代不再受宿主打包了旧版本插件框架所限制。
  • 宿主增量极小:得益于全动态实现,真正合入宿主程序的代码量极小(15KB,160方法数左右)。
  • Kotlin实现:Core.Loader,Core.Transform核心代码完全用Kotlin实现,代码简洁易维护。

Shadow的逻辑结构

市面上有很多插件框架,但是除了核心的免安装运行系统组件的目的之外,每个插件框架的功能都有自己的范围。所以先介绍一下Shadow的逻辑结构,以便大家了解Shadow的大致功能范围。

Shadow(Shadow框架分为Core和Dynamic两部分)
    Core(Shadow的核心功能)
        Loader(免安装运行实现)
        Runtime(运行时类库)
        Gradle-Plugin(插件App构建插件)
        Manager(插件安装管理器)
    Dynamic(将Core层的所有功能动态化起来)

对照这个逻辑结构,可以将Shadow的功能和实现大致描述出来:Shadow通过在插件App的构建过程中添加一个Gradle插件,运用AOP编程思想,以修改App字节码为手段,将一个Shadow Runtime的中间层加入到插件App中。使插件App不再与系统直接交互,进而达到无需Hack系统的目的。同时,Shadow还有另一大特点,即全动态实现,Dynamic层将插件加载和管理以及运行时类库的一切代码都动态化起来,使Shadow可以在应用发布后继续迭代扩充功能、修复Bug。

支持特性

  • 四大组件
  • Fragment(代码添加和Xml添加)
  • DataBinding(无需特别支持,但已验证可正常工作)
  • 跨进程使用插件Service
  • 自定义Theme
  • 插件访问宿主类
  • So加载
  • 分段加载插件(多Apk分别加载或多Apk以此依赖加载)
  • 一个Activity中加载多个Apk中的View
  • 等等……

采用Shadow的项目

  • Now
  • QQ群视频
  • 花样直播

代码介绍

必须用Android Studio 3.4或更高版本打开工程

由于我们需要在SDK开发工程中有一个调试SDK用的Demo程序,这个Demo程序需要直接源码依赖SDK,才能在修改SDK后直接生效。而SDK中包含了在编译期需要使用到的Runtime和Gradle-Plugin模块,而这两个部分又是编译期的结果。所以为了达到这个目的,我们使用了Gradle的复合构建。但是又由于我们在配置期和编译期同时使用了Runtime这个模块,所以触发了Gradle早期版本的Bug。因此我们必须使用Gradle 5.0或更高版本,而Android Studio在3.4版本才支持Gradle 5.0版本。是的,我们是使用Android Studio 3.4 Preview版本开发的Shadow,好在这个Preview版本非常稳定。

这是一个标准的Android工程。可以用Android Studio直接打开项目根目录。出于习惯,我们没有上库IDE相关的任何文件。

首次打开工程时遇到SDK location not found.

https://git.oa.com/shadow/shadow/issues/14

编译失败遇到Failed to find byte code for com/tencent/shadow/runtime/....

请关闭Android Studio的Instant Run功能。

代码结构

项目的代码都在projects子目录中,根目录中的其余文件都是Gradle相关的构建脚本。

Shadow SDK的代码都位于projects/sdk中。Demo代码位于projects/demo中。整个项目是一个复合构建。Demo代码以源码依赖方式依赖了SDK。

Demo说明: projects/demo/host-apk是一个宿主App程序,该宿主APP没有直接打包插件框架,演示了动态加载插件安装管理、插件框架动态加载、插件动态加载的过程,在构建过程中会自动构建出demo-plugin.apk以及loader.apk、runtime.apk、pluginmanager.apk及配置json构成的插件压缩包,并将它们都打包到自己的assets中,因此可以直接运行启动插件。

projects/demo/plugin-app/demo-plugin是一个Android Application模块,它将projects/demo/plugin-app/demo-main打包成插件。 projects/demo/loader-apk 是一个Android Application模块,它打包了sdk/core/loadersdk/dynamic/loadersdk/dynamic/loader-impl模块,并配置了对应插件的组件和宿主组件的关系,可动态加载。 projects/demo/runtime-apk 是一个Android Application模块,它打包了sdk/core/runtime模块,并定义了宿主中注册的Activity组件,可动态加载。 projects/demo/pluginmanager-apk 是一个Android Application模块,它打包了sdk/core/managersdk/dynamic/managersdk/dynamic/loader模块,并实现了插件安装管理启动,可动态加载。

projects/demo-none-dynamic是宿主APP直接打包插件框架的演示程序。此Demo主要用于保证SDK开发时core层可以单独使用,与dynamic层解耦。 在构建过程中会将projects/demo/plugin-app/demo-plugin自动构建出并打包在自己的assets中,因此它可以直接运行并将插件App以免安装方式运行起来。

注意: projects/demo/plugin-app/demo-plugin是不能正常安装运行的,运行时会出现类找不到的Crash。

About

零反射全动态Android插件框架

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 77.6%
  • Kotlin 22.2%
  • Other 0.2%