往期参考:

  1. 需求定义
  2. 基本原理
  3. 插件实现
  4. 资源覆盖

插件形式

插件一般是独立Apk形式,但是也可以内置集成在应用里面,这些模块也可以注册为虚拟插件,由插件管理模块统一管理。

虚拟插件包含“宿主插件”这一特殊插件,、它将宿主APP虚拟为一个插件,主要用于资源覆盖中作为覆盖目标。

 

 

插件环境

插件环境是指插件运行所依赖的环境。不同的插件需要不同的环境,有的插件可以在多个环境下运行。

插件环境通过一个接口类表示,在插件描述中需要表明插件可以工作的环境,可以列出多个;同时,插件类也需要继承这些接口,内置插件通过插件类继承的接口来达到同样的效果,虽然这可能是多余的。

 

 

插件集成

插件集成方式及对应目录(以优先级顺序排列):

集成方式

扫描目录

说明

应用升级插件

/data/data/<package>/cache/plugins/

应用缓存目录

外部升级插件

/sdcard/<package>/cache/plugins/

/data/data/<package>/cache/plugins/external/

从USB目录拷贝到该目录

没有扩展sdcard时

应用内置插件

/data/data/<package>/cache/plugins/assets/

从应用assets资源解压出来

系统升级插件

/data/xxxplugins/

全局的,限系统预置应用使用

系统预置插件

/system/xxxplugins/

全局的,限系统预置应用使用

应用集成插件

没有插件形式,但是作为插件统一管理

注册Plugin入口类

虚拟应用插件

将应用特殊虚拟为一个插件

目前用于皮肤覆盖

 

 

插件加载

加载流程

  1. 导入插件
  1. 外部插件:通过插件Context,加载插件描述
  2. 内置插件:已经提供插件类,没有额外描述
  1. 依赖检查
  1. 检查环境依赖,过滤
  1. 外部插件:检查插件描述中的环境依赖
  2. 内置插件:检查插件实现的环境接口
  1. 检查插件依赖(递归)
  1. 检查插件依赖,如果依赖插件不存在,则依赖性失败
  2. 递归依赖插件,如果依赖插件检查失败,则当前插件依赖性失败
  1. 启动插件(递归)
  1. 如果有依赖,先启动依赖插件
  2. 构建插件ClassLoader(内置插件跳过)
  3. 加载插件类(内置插件跳过)
  4. 创建插件类实例
  5. 调用插件实例的start方法
  1. 清除未使用插件

因为所有的检查都先做了,所以环境不相关的插件在清除后都不会留下痕迹。启动失败的插件可能会遗留插件类,导致插件部分资源不能释放。

 

 

 

延迟加载

插件加载过程中包含dex优化和so库解压等步骤,这些步骤都比较耗时。为了减少应用首次启动的时间,应该将插件的一部分加载步骤推迟。

具体方案为:

  • 推迟“启动插件”这一步,不影响依赖检查
  • 虚拟插件不推迟
  • 资源包不推迟

 

缓存管理

缓存目录:

集成方式

缓存目录

特殊说明

应用插件

/data/data/<package>/cache/plugins/

包括:应用升级插件、外部升级插件、应用内置插件、应用集成插件、虚拟应用插件

系统升级插件

/data/xxxplugins/

皮肤覆盖仍使用应用内部缓存

系统预置插件

/data/xxxplugins/

皮肤覆盖仍使用应用内部缓存

APK时间是“系统构建时间”与“实际APK时间”取大者

可使用预置资源(odex,so)

缓存项目:

项目

缓存子目录

特殊说明

锁文件

缓存根目录

 

Native库

lib

 

Dex优化

dex

Android O以上无效

配置文件

props、缓存根目录

老版本配置文件解压在缓存根目录

资源覆盖

idmap

覆盖目标包的缓存目录,

 

 

插件更新

未完待续