大发快三官方爱奇艺开源 Qigsaw,基于 Android App Bundle 的动态化框架

  • 时间:
  • 浏览:45

近日爱奇大发快三官方艺宣布开源基于Andro大发快三官方id App B大发快三官方undle的动态化框架 Qigsaw。以下是其官方在演讲中对项目的介绍。

当我们 于2019年6月26号正式开源Qigsaw。

Qigsaw是爱奇艺自主研发的动态化框架,其核心优势如下:

  1. 利用Android App Bundle开发套件,极速开发体验。
  2. 支持Android App Bundle所有功能形态,"山寨"Play Core Library公开接口实现,开发者阅读官方文档即可愉快开发。
  3. 任何系统程序均可动态加载插件,支持Android四大组件动态加载。
  4. 否则您的应用有出海需求,可无缝切换至Android App Bundle方案。
  5. 仅一处Hook,血块私有API访问,保证框架稳定性。

Android动态化方案,在国内已蓬勃发展数年之久,其核心目的是减少应用包体积,提升应用安装率。Google在减少应用包体积上的探索也从未停息,下面当我们 一起去来看看Google在这方面的努力。

Google减少应用包体积方案演进

回首Android***个10年,其应用发布法律法律依据如下。

从应用开发到上传应用商店,***再到用户下载环节,参与产物都是APK。

您的应用将富含所有CPU架构so文件、所有屏幕分辨率资源文件以及所有语言资源文件,那么所处如下另几次多多大问题。

  1. APK文件过大原因 用户下载时长增加。

  2. 血块越多再被使用的代码和资源侵占用户磁盘空间。

在国内,开发者一般都只会放五种CPU架构的so文件和五种屏幕分辨率资源文件,以此来减少包体积,但你是什么法律法律依据一定程度上会影响用户体验。

根据Google官方数据统计,从2012年至今,应用包体积平均增长了5倍左右,爱奇艺可是我我例外。

经过七年发展,爱奇艺那么"膨胀"。

Google意识到包体积大问题的严峻性,于Android 5.0推出Multiple APK,旨在减少安装包体积。

Multiple APK

Multiple APK是Google Play提供另几次多多功能,它允许您的应用针对不同的设备配置发布不同的APK。通过一张图来了解下其工作流程。

图中左边手机是nexus 5,右边手机是nexus 6p,它们的CPU架构、屏幕分辨率均不同,否则Google Play会根据当前设备配置下载对应APK。

Google提供打包配置选项,让开发者根据不同设备配置生成不同APK文件。

  1. android { 
  2.   ... 
  3.   splits { 
  4.  
  5.      
  6.  
  7.   density { 
  8.      ... 
  9.       
  10.       exclude "ldpi""xxhdpi""xxxhdpi" 
  11.     } 
  12.      
  13.  
  14.     abi { 
  15.       ... 
  16.        
  17.       include "x86", “x86_64" 
  18.  
  19.        
  20.       universalApk false 
  21.     } 
  22.   } 

通过density abi 另几次多多配置维度即可生成一系列APKs。

上图中生成的产物,通过文件名当我们 可不可不可否 很清楚知道该APK作用于何种配置的设备。

Android设备的多样性,原因 Multiple APK并未朝着Google期待的方向发展。否则您有否则为每个版本构建数百个APKs,大大降低迭代效率。国外开发者对此也并不感冒,这也成为Google的一块心病。

Android App Bundle

Android App Bundle是五种全新的应用上传格式(.aab),它富含所有编译代码和资源。当您上传aab文件至Google Play后,Google Play将aab文件拆分成一系列APKs并签名。

此外,您可不里可不可否 在应用项目中换成dynamic feature模块,哪些地方地方模块并不时要在应用***安装时一起去被下载安装。您可不可不可否 通过使用Play Core Libray在应用运行过程中动态安装dynamic feature。dynamic feature类似国内插件化提供的能力,但dynamic feature功能更强大。

通过上图,可不可不可否 看一遍dynamic feature可不可不可否 基于设备配置选择 对应的Configuration Split APKs,那么可不可不可否 进一步减小dynamic feature安装包体积。

更多关于Android App Bundle细节,请阅读官方文档,本文不再赘述。

Android App Bundle人太好可不可不可否 支持应用运行期间安装dynamic feature,得益于Android 5.0推出的Split APKs功能。

Split APKs

Split APKs是Android 5.0引入的五种全新应用安装机制,其目的是为出理 APK体积日益增大大问题。Split APK可不可不可否 将另几次多多完整性庞大的APK按照CPU架构、屏幕密度等维度拆分成多个独立APKs。当应用APK下载更新时,法律法律依据当前设备配置选择 对应配置APKs安装即可。

Android 5.0后来,另几次多多APK代表另几次多多应用。在Split APKs问世后来,另几次多多应用否则对应多个APKs。所有Split APKs拥有相同包名和签名。

Android提供五种法律法律依据安装Split APKs。

  1. adb install-multiple [base-apk, split1-apk]
  2. PackageInstaller.

vivo手机不支持adb install-multipl命令。

这里当我们 重点介绍第二种安装法律法律依据,Android 5.0提供PackageInstaller用于安装Base APK和Split APKs。

当第三方应用通过PackageInstaller在应用运行期安装Split APKs时,系统会启动安装器界面供用户选择 与非 安装此次更新。

在用户选择 安装后,应用否则被系统“杀死”。当应用再次启动后来,Split APKs就会生效。

在当我们 实际测试过程中,否则 国产手机对PackageInstaller有改动,原因 无法正常安装Split APKs。

系统应用可不可不可否 静默安装Split APKs,且当Split APKs安装完成后,可不可不可否 决定与非 “杀死“应用系统程序。

  1. public static class SessionParams implements Parcelable { 
  2.  
  3.     ... 
  4.  
  5.      
  6.     @SystemApi 
  7.     public void setDontKillApp(boolean dontKillApp) { 
  8.        if (dontKillApp) { 
  9.            installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 
  10.        } else { 
  11.            installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP; 
  12.        } 
  13.     } 
  14.     ... 
  15.     ... 

SessionParams是PackageInstaller內部类,setDontKillApp可决定当APK安装完成后与非 杀死应用系统程序。setDontKillApp属于系统Api,否则第三方应用无法调用。

Split APKs加载

应用系统程序所使用到的ClassLoader和Resources均在LoadedAPK中创建。

通过Android 9.0 LoadedAPK源码片段,当我们 一起去了解下Split APKs加载过程。

ClassLoader创建。

通过createOrUpdateClassLoaderLocked法律法律依据名,可不可不可否 知道该法律法律依据是用于创建和更新ClassLoader。该法律法律依据有另几次多多核心步骤。

  1. 否则mClassLoader为空,则创建PathClassLoader实例。

  2. 否则addedPaths不为空,则更新PathClassLoader实例。

该法律法律依据指明,应用系统程序是可不可不可否 动态加载Split APKs代码。

Resources创建。

通过getResources法律法律依据代码片段,可知Split APKs的资源路径作为mResources创建参数。

关于更多Split APKs加载原理细节,请阅读相关Android源码。

Play Core Library

文章开始英语 英语 英语 介绍Qigsaw核心优势有提到,Qigsaw"山寨"Play Core Library公开接口实现,开发者阅读其官方文档即可开发。否则,在此主要介绍下Play Core Library工作流程。

当爱奇艺App在运行过程中,用户时要使用大发快三官方游戏插件,会经历以下过程。

  1. 爱奇艺App通过Play Core Library发起游戏APK安装请求。

  2. 当Google Play收到请求后,首先请求游戏APK相关数据信息,请求成功后开始英语 英语 英语 下载并安装游戏APK。

  3. 在请求、下载以及安装整个过程中,Google Play会将整个过程所有情况报告返回给爱奇艺App,包括请求结果、下载进度、安装结果等。

  4. 当安装完成后来,爱奇艺App就可不可不可否 使用游戏APK。

在Android 7.0版本后来,当Split APK安装完成后来,应用无法立即使用Split APK。否则Play Core Library提供SplitCompat模式让App可立即使用Split APK。

爱奇艺动态化框架Qigsaw

在2018年上五天,当我们 就进行动态组件化方案的调研。起初方案是基于Instant App方案实现,当整体功能基本实现后,Google于2018年Google IO大会上推出Android App Bundle。在调研Android App Bundle后来,当我们 发现Android App Bundle完整性符合最初的需求。

法律法律依据当我们 最初设计初衷和Android App Bundle特点,总结出Qigsaw应满足以下核心特点。

  1. 利用Android App Bundle开发套件,体验原生极速开发体验。
  2. 血块私有Api访问,保证框架稳定性。
  3. 否则您的应用有出海需求,可无缝切换至Android App Bundle方案。

关于私有Api访问应该是当我们 比较关心的,最近一段时间某大厂开源了号称零反射插件化框架,否则通过阅读其源码,当我们 发现它还是做了PathClassLoader的parent ClassLoader反射替换。另外它也调用了Resources构造法律法律依据创建Resources实例,人太好 原本 做并那么任何私有Api访问,否则通过查看Resources构造法律法律依据源码,当我们 可知该法律法律依据属于过时法律法律依据,且注释写明第三方应用不应该创建Resources实例。

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  @Deprecated 
  15.  public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { 
  16.      this(null); 
  17.      mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()); 
  18.  } 

否则 插件化框架不应该仅仅以与非 零反射为目标,当我们 应该从开发流程及产品形态选择 相当于方案,助力开发效率。

Qigsaw开发体验

在开发阶段,开发者使用Android App Bundle原生开发套件即可开发调试Split APKs。

Android App Bundle为dynamic feature提供全新插件com.android.dynamic-feature,它的编译产物是.apk文件。当您的项目编译完成后,Android Studio通过命令adb install-multiple命令将base apk和split apks安装至您的手机。否则您的开发手机系统版本低于5.0,则会法律法律依据当前手机设备组装成另几次多多完整性apk文件安装至该手机。

vivo手机不支持split APKs功能,否则在开发过程中请选择 否则 手机。否则使用Qigsaw打包插件提供的qigsawAssemble${variantName}命令

在发布阶段,Qigsaw提供打包插件让开发者享受一条龙服务,开发者并不关心dynamic feature的上传派发。

Qigsaw打包插件支持内置dynamic feature,所有内置dynamic feature总要被拷贝至base apk的assets目录。对于非内置dynamic feature,Qigsaw打包插件会将其上传至CDN服务器,出理 业务方后顾之忧。

Qigsaw原理

Qigsaw借助Android App Bundle开发套件完成dynamic feature的打包,大大降低Qigsaw开发维护成本。否则Qigsaw关心的重点落在否则安装加载dynamic feature生成apk上。

第三方应用利用PackageInstaller安装split APKs体验极其不友好,且否则 国产手机对split APKs功能支持不完善,否则 当我们 最终还是按照一般插件化法律法律依据安装加载split APKs。

法律法律依据上图,否则时要动态加载split APKs,时要出理 代码、资源以及四大组件的加载。

Split APKs代码加载

针对splits代码加载,Qigsaw采用单类加载器法律法律依据,即base APK和split APKs采用同一ClassLoader加载。

在DexPathList中,为每个split创建对应的ElementNativeLibraryElement实例即可。关于单类加载器更多细节,本文不再赘述,相关原理已非常心智心智成长期图片 图片 图片 是什么是什么。

Split APKs资源加载。

Splits资源加载相较于代码加载会繁杂,否则不同系统版本或不同手机厂商总要所处否则 兼容性大问题。

Android Gradle Plugin在资源打包时,会对res目录下资源文件分配另几次多多唯一Id。

Id前两位PP为Package Id,代表应用类型。是系统应用、第三方应用、Instant App或Dynamic Feature等。

Id后面 两位TT为Type,代表资源类型。是drawable、layout或string等。

Id后四位EE为Entry,代表该资源顺序。

所有第三方应用base APK资源Package Id均为7F,Android App Bundle对splits资源打包总要基于7F依次递减分配Package Id。否则,即使当我们 将split APKs资源换成到当前应用Resources实例中,可是我我会老出资源冲突大问题,splits访问base资源也更加方便。

Instant Apps资源打包是基于7F依次递增。

通过Android App Bundle出理 splits资源打包大问题,那么splits资源如何加载呢?当我们 来看一段代码。

Qigsaw提供loadResources法律法律依据加载split APKs资源。为出理 开发者写血块模板代码,Qigsaw打包插件采用字节码操作法律法律依据自动写入该法律法律依据。

Split APKs四大组件加载

Android App Bundle在Manifest文件合并过程中,会将split APKs manifest文件内容合并至base APK中。否则,所有split APKs四大组件信息都与非 则声明在base APK中。

Android App Bundle你是什么出理 法律法律依据不支持Manifest更新,类似新增四大组件,否则 Qigsaw可是我我支持新增四大组件。在正常开发迭代过程中,动态新增splits四大组件需求极少,否则 Qigsaw与Android App Bundle形态保持一致。

Split APKs安装过程

前文当我们 介绍了Play Core Library是如何安装、加载split APKs,Qigsaw安装、加载split APKs与Play Core Library类似。首先,通过一张图来了解。

在爱奇艺App运行过程中,当X系统程序发起安装游戏APK请求时,会经历以下步骤。

  1. X系统程序通过Qigsaw Core Library发起游戏APK安装请求。

  2. 当主系统程序收到请求后,开始英语 英语 英语 下载并安装游戏APK。

  3. 在下载、安装整个过程中,Qigsaw Core Library会将整个过程所有情况报告返回给爱奇艺App,包括下载进度、安装结果等。

  4. 当安装完成后来,爱奇艺App就可不可不可否 使用游戏APK。

Qigsaw下载、安装split APKs均在主系统程序出理 ,split APKs的加载则所处在X系统程序。Qigsaw安装、加载split APKs原则是,哪个系统程序发起split APKs安装请求,就在哪个系统程序加载split APKs。

Qigsaw拓展功能

在实际开发过程中,Android App Bundle所支持的功能形态并不满足当我们 需求。否则,Qigsaw在Android App Bundle基础上拓展了几次功能。

  1. Split APKs的Application初始化。
  2. Split APKs的Content Provider动态加载。
  3. 多系统程序支持。
  4. 通过Tinker patch完成split APKs热更新。

在此,当我们 首先介绍Qigsaw多系统程序功能。以下图场景为例。

法律法律依据Qigsaw安装、加载split APKs原则,当游戏APK安装完成后,就会在主系统程序完成加载。在游戏APK富含另几次多多Activity,当我们 所处系统程序不同。当启动GameActivity01时,页面正常启动。但当启动GameActivity02,您的App会老出崩溃。原因 是GameActivity02运行在:game系统程序,游戏APK仅在主系统程序加载,并未在:game系统程序加载,否则系统会抛出ClassNotFoundException异常。

为出理 类似大问题,Qigsaw提供了如下出理 方案。

  1. 在系统程序启动之初即Applicatin#attachBaseContext调用时,加载所有已安装splits。
  2. Hook PathClassLoader。

***种方案出理 的场景是:game系统程序***启动,即启动GameActivity02后来:game系统程序从未启动过。

第二种方案出理 的场景是:game系统程序否则启动并正在运行。

Hook PathClassLoader具体做了如下事情。

  1. 当老出ClassNotFoundException时,判断该类与非 为splits四大组件。
  2. 当异常类为splits四大组件时,加载所有已安装未加载split APKs。
  3. 如加载完所有已安装未加载split APKs后依然老出ClassNotFoundException异常,则返回空四大组件类,出理 系统程序崩溃。

否则split APKs某Activity的exported熟悉为true,那么该Activity否则会在split未安装的情况报告下被外界调起。当老出你是什么情况报告时,Qigsaw返回空Activity类出理 系统程序崩溃。

国内否则 App都接入Tinker用于修复线上bug,爱奇艺同样也接入。Qigsaw五种提供热更新能力,但在实际开发过程中发现,Qigsaw能借助Tinker Patch热更新split APKs,提升开发效率。

Qigsaw在打***程中会生成关于富含split信息的.json文件,该文件存储在base APK的assets目录下。其命名规则为App版本号_Split信息版本号.json

json文件记录的内容如下。

  1.   "qigsawId""1.0.0_ddddf54"
  2.   "appVersionName""1.0.0"
  3.   "splits": [ 
  4.     { 
  5.       "splitName""java"
  6.       "url""assets://java.zip"
  7.       "builtIn"true
  8.       "size"13915
  9.       "version""1.1@1"
  10.       "md5""9ea0f98381dea0d16a313ea9c09cc4aa"
  11.       "workProcesses": [ 
  12.         ":qigsaw"
  13.         "" 
  14.       ], 
  15.       "minSdkVersion"14
  16.       "dexNumber"4 
  17.     }, 
  18.     ... 
  19.     ... 
  20. }     

该文件记录着splits版本号以及下载地址,否则Tinker开启资源修复,当我们 就可不可不可否 通过tinker patch更新该json文件,以此达到热更新splits目的。

Qigsaw的未来希望都总要你参与

Qigsaw 在 2019 年 1 月正式在爱奇艺 App 上线,五天间经过数亿用户验证,由 Qigsaw 引起的崩溃率占总崩溃率已不足千分之一。在爱奇艺 App 中,小系统程序以及小游戏框架均由 Qigsaw 动态加载,目前已推广至全公司5个业务线团队使用。2019 年 6 月 26 日,Qigsaw 正式对外开源,当我们 希望有志之士能为 Qigsaw 贡献一己之力,一起去完善 Qigsaw 生态,让国内更多开发者体验到 Android App Bundle 的快感。

***,否则您认可Qigsaw,欢迎当我们 献上买车人的小星星,star关注当我们 吧!

【编辑推荐】

【责任编辑:

张燕妮

TEL:(010)6847660 6】



点赞 0