第三方应用利用PackageInstaller安装split APKs体验极其不友好,且某些国产手机对split APKs功能支持不完善,所以我们最终还是按照一般插件化方式安装加载split APKs。
依据上图,如果需要动态加载split APKs,需要解决代码、资源以及四大组件的加载。
针对splits代码加载,Qigsaw采用单类加载器方式,即base APK和split APKs采用同一ClassLoader加载。
在DexPathList中,为每个split创建对应的和NativeLibraryElement
实例即可。关于单类加载器更多细节,本文不再赘述,相关原理已非常成熟。
Splits资源加载相较于代码加载会复杂,因为不同系统版本或不同手机厂商都会存在一些兼容性问题。
Id前两位为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资源也更加方便。
通过Android App Bundle解决splits资源打包问题,那么splits资源如何加载呢?我们来看一段代码。
Qigsaw提供方法加载split APKs资源。为避免开发者写大量模板代码,Qigsaw打包插件采用字节码操作方式自动写入该方法。
Android App Bundle这种处理方式不支持Manifest更新,例如新增四大组件,所以Qigsaw也不支持新增四大组件。在正常开发迭代过程中,动态新增splits四大组件需求极少,所以Qigsaw与Android App Bundle特性保持一致。
前文我们介绍了Play Core Library是如何安装、加载split APKs,Qigsaw安装、加载split APKs与Play Core Library类似。首先,通过一张图来了解。
在爱奇艺App运行过程中,当X
进程发起安装游戏APK请求时,会经历以下步骤。
X
进程通过Qigsaw Core Library发起游戏APK安装请求。在下载、安装整个过程中,Qigsaw Core Library会将整个过程所有状态返回给爱奇艺App,包括下载进度、安装结果等。
当安装完成以后,爱奇艺App就可以使用游戏APK。