qigsaw插件化流程解析

aab方式介绍

Android App Bundle

一种发布格式,将所有经过编译的代码和资源包含在一个构件工件中;
是经过签名的二进制文件,可将应用的代码和资源组织到模块中;

请添加图片描述

简单来说, android插件化是 分为 base apk 和feature apk;
base 为基础包; feature为单个模块包, 可通过cdn网上动态下载 ,动态添加需要的功能模块;

组件化和插件化的区别:

同:

  • 两者都可以使基础包和模块包作为一个app运行,便于开发;
  • 充分解耦;

异:

  • 组件化还是作为统一的app,只是开发时作为单独的app;
  • 插件化所有模块就是单独的app,但单个模块不能安装,由基础包统一调动;

apk拆分

  • 基本apk: 包含所有其他apk都可以访问的代码和资源,并提供应用的基本功能;
  • 配置apk: 每个配置apk都包含针对特定屏幕密度,cpu架构或语言的原生库和资源;用户只会下载与设备对应的apk;
  • 功能模块apk: 包含模块化处理的功能的代码和资源,

请添加图片描述

分发分类

  • 安装时分发
  • 按需分发
  • 根据条件提供
  • 免安装分发

Qigsaw 插件化介绍

原地址文档

Qigsaw_wiki

爱奇艺提供的 一套基于 Android App Bundle(AAB) 的动态化方案;

特点:

  • 单base apk + 多个Split apk;
  • apk 安装后,可以按需请求下发或者更新模块apk;
  • api 21(5.0) 以上使用,低版本下发完整apk;

优势:

  • 使用aab原生的开发套件 google 的 play core library 公开接口实现,支持所有aab的功能特性;
  • 任何进程均可动态加载插件,支持四大组件;
  • 可无缝切换aab方案
  • 仅一处hook(android9.0+无需hook),少量私有api;

方案:

  • 基线工程和插件工程独立开发,基线工程提供基础sdk供插件工程编译使用,避免类重复;
  • 插件化方案一般将插件app 运行在 :plugin 插件进程,用ipc方案进程间通信;

请添加图片描述

当项目编译完成后,可通过adb install-multiple命令将baseapk和插件apk安装到手机中;

请添加图片描述

qigsaw打包插件支持内置插件,所有内置插件都会拷贝到base apk 的assets目录; 非内置插件,qigsaw打包插件会将其上传到cdn服务器,解决业务方后顾之忧;

apk 安装命令

aab安装或者defalutApk安装都是通过adb install-multiple命令来安装baseapk和splitapks;

  • 多apk安装,必须保证baseapk存在; 如 base-master.apk、base-xxhdpi、base-zh.apk 三个apk的安装;
  • 已安装baseapk,继续安装splitapk,添加 -p参数(partial application install) 部分安装, 后跟baseapk包名;

apk update 步骤

ondemand =true表示按需分发 即不会将插件模块打进主apk中 而是上传到服务端 随后在apk安装之后进行下发 不过目前插件化模块的上传逻辑我们并没有实现 所以其实只能支持设置ondemand =false

  • 创建插件更新分支,修改代码;
  • 修改插件版本号;
  • 配置qigsawSplit中的版本号;
    • splitInfoVersion
    • 配置mapping
    • 配置old apk
  • 再次执行qigsawAssemble${variantName}

Qigsaw 源码分析

前言:

Qigsaw结构主要分为:

  • 编译期的Aop ; 由QigsawPlugin实现,主要是经transform api 处理四大组件的Resource对象和生成统计Split模块中四大组件等信息的ComponentInfo类,涉及到的主要技术点关键词为:ASM ,TransformApi, gradleTasks
  • 运行期插件的获取和激活; 主要分为split的安装和加载过程,涉及到的主要技术点关键词为:Binder通信,ClassLoader,loadDex
Qigsaw plugin 源码分析

QigsawAppBasePlugin app模块应用的插件

注册的transform

  • SplitComponentTransform (taskName:processSplitComponent) 处理split manifest文件, 生成class文件记录除provider的信息,生成代理provider
    • 通过模块的copySplitManifestTask 在split模块的Manifest生成后会将xml复制到临时目录;
    • 读取临时目录中所有split的xml,获取activity,service,receiver,provider和application的名称,建立Map添加key为featureName和各组件大写后缀名,value为各组件名称的键值对;
    • Asm创建com.iqiyi.android.qigsaw.core.extension.ComponentInfo类,遍历Map,Asm写入属性
      • application: 创建常量属性
      • provider:构建providerName + _Decorated_ + splitName作为代理provider的名称,asm创建代理Provider继承自com.iqiyi.android.qigsaw.core.splitload.SplitContentProvider;此代理provider会在AABExtension激活split时处理;
      • 其他: 创建,分隔的常量属性
  • SplitResourcesLoaderTransform (taskName: splitResourcesLoader) 主要是在组件中插入 SplitInstallHelper#loadResources}方法,此处transform处理jar和Directory的字节码;
    • 如果是基线包
      • 获取插件扩展参数的act,对参数中指定activity使用SplitActivityWeaver进行方法的注入操作:
        • SplitActivityWeaver: 访问activity的所有方法,在getResources方法中(注意:没有此方法则新建插入,有则直接插入 )注入SplitInstallHelper#loadResources方法,即通过SplitCompatResourcesLoader#loadResources加载插件资源;
    • 如果是插件包
      • 获取split的mergedManifest文件,读取activities,services,receivers,分别使用各自的Weaver 进行编织:
        • SplitServiceWeaver: 访问service的所有方法,在onCreate方法中注入SplitInstallHelper#loadResources方法
        • SplitReceiverWeaver: 访问receiver的所有方法,在onReceive方法中注入SplitInstallHelper#loadResources方法

主要的tasks

  • ExtractTargetFilesFromOldApk : 如果插件参数中设置oldApk,则复制assets/qigsaw/**目录文件到临时目录;
  • GenerateQigsawConfig: 构建 QigsawConfig.java 文件, 注意如果指定了oldApk,qigsawId即为oldApk中的qigsawId;
  • Split:copySplitManifestTask: 取split合并后的manifest,复制到app的临时目录;
  • Split:ProcessSplitApkTask :在split的assembleTask运行后,处理生成的splitApk,按照abi收集apkData信息,支持单个abi打包,最终会生成一个签名后的apk包和单个split.json记录split的信息,默认的apkData.url为asset://开头,buildIn标记(qigsawAssembleTask中用于判断是否上传至cdn中的标记) 由manifest中onDemand和插件参数releaseSplitApk 决定 boolean builtIn = !onDemand || !releaseSplitApk
  • QigsawProcessManifestTask: 将app中merge/bundleManifest 的provider和splitManifest中的代理Provider 做同名处理,将同名的appProvider名称修改为providerName + _Decorated_ + splitName在写回,用于启动时AABExtension的解析;
  • CreateSplitDetailsFileTask :即qigsawAssembleTask,真正的打基线包的Task
    • 先获取所有split生成的json信息
    • 生成SplitDetails信息,收集app的所有打包信息
      • 如果设置了oldApk,会判断是否是更新态,如果不是更新态直接使用oldApk中的SplitDetails信息;
      • 如果是更新态,获取oldApk 的qigsaw.json信息,判断如果当前打的包moduleVersion(versionName@versionCode)和oldApk中的同一splitModule的version是否相同,如果split版本变化意为split的版本已经更新,标记当前更新状态,添加当前splitName到updateSplits字段中,创建SplitDetails对象;
      • 如果当前的split的buildIn参数为false,尝试上传操作,上传成功指定apkData.url 为http://开头数据,表示在qigsaw安装阶段会从本地的asset目录获取apk还是从网络路径获取apk;
    • 根据依赖关系重排序splitInfo 列表,根据SplitDetail写出qigsaw.json文件,获取当前abi列表数据并写出baseAppCpuAbiListFile文件,此文件也会复制到asset目录;
    • 当前split的buildIn为true,如果是更新状态则将每个split的已签名的apk复制到即将打包的asset目录中,否则直接复制oldApk中的apk;
  • SplitBaseApkForABIsTask:packageAppTask之后运行,用于根据baseAppCpuAbiListFile文件缩减到指定的abi的再输出apk;
  • QigsawProguardConfigTask: 额外添加qigsaw的混淆和接收插件参数mapping文件保持混淆的一致性;

QigsawDynamicFeaturePlugin feature模块应用的插件

FeaturePlugin 注册 SplitResourcesLoaderTransform 和 SplitLibraryLoade

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值