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。

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

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

这里我们重点介绍第二种安装方式,Android 5.0提供PackageInstaller用于安装Base APK和Split APKs。

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

install_split_apks

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

在我们实际测试过程中,某些国产手机对PackageInstaller有改动,导致无法正常安装Split APKs。

系统应用可以静默安装Split APKs,且当Split APKs安装完成后,可以决定是否“杀死“应用进程。

  1. public static class SessionParams implements Parcelable {
  2.  
  3. ...
  4.  
  5. /** {@hide} */
  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. ...
  16. }

SessionParams是PackageInstaller内部类,setDontKillApp可决定当APK安装完成后是否杀死应用进程。setDontKillApp属于系统Api,因此第三方应用无法调用。

Split APKs加载

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

loadedapk

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

ClassLoader创建。

create_classloader

通过createOrUpdateClassLoaderLocked方法名,可以知道该方法是用于创建和更新ClassLoader。该方法有两个核心步骤。

  • 如果mClassLoader为空,则创建PathClassLoader实例。

  • 如果addedPaths不为空,则更新PathClassLoader实例。

该方法指明,应用进程是可以动态加载Split APKs代码。

Resources创建。

create_resources

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

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