This article is just a guide to the PkMS, not a lot of code analysis, look at the source code, more based on method analysis of the implementation logic, and the code is based on Android 11, compared with the previous Android 10 code is quite different.

In this paper, the content

  1. Why use AppBundle
  2. The use of AppBundle
  3. What is the structure of AppBundle and how is it installed into an application

Why use AppBundle

The reason is simple —-APK slimming. If you are an app developer, there should be a lot of pain in APK slimming, and AppBundle is a way for the system to slim down APK. So how does AppBundle slim down apK? The principle is to remove unnecessary resources. How to remove? According to the system’s immutable configuration, what is a configuration? Configuration is a property of a phone or system. The most common one is the horizontal and portrait screen, virtual keyboard, and screen resolution.

Configuration is divided into variable and immutable. I distinguish them by myself. For example, virtual keyboard, horizontal and vertical screen, and MCCMNC (SIM card logo) belong to variable configuration. Immutable configuration also includes: screen resolution, supported system language, 32-bit or 64-bit system, these system inherent properties are immutable. You can save a lot of space by separating the resources of the original APK into the server and importing only the required resources when installing the application. For example: In order to be compatible with Android fragmentation process, we need to set mdPI, HDPI, XHDPI and XXHDPI resources for different resolution applications. Although there are SVG images, complex images still need JPEG or PNG images. If each resolution is added, Then apK will undoubtedly be very large. However, when the app store delivers the application, it obtains the resolution of the current phone in advance and sends the APK to the back-end server. Then the server sends the corresponding APK according to the transmitted information, and the size of APK will be greatly reduced.

The use of AppBundle

Tools needed:

  1. Android Studio, make sure Android Studio version is greater than 3.2 and Gradle version is not less than 3.2.1
  2. Bundletool, used for format conversion, needs to be downloaded from Github

Generate aAB format

Build->Generate Signed Bundle/Apk->Android App Bundle ->Generate Signed Bundle/Apk->Android App Bundle ->Generate Signed Bundle/Apk->Android App Bundle ->Generate Signed Bundle/Apk->Android App Bundle You want to convert it to apK

Use Bundletool to convert the package to apKS

Bundletool is not a script, it is a jar package, so you can use the Java -jar bundletool_version.jar. The rest of the parameters will be the same and we will have a israel-border directory that will have the rest of the split APKs

  1. Base. Apk, the name of this APK might be base-master.apk, it doesn’t matter, the important thing is that it doesn’t have a split flag and it has a dex file
  2. Apk is a Chinese language resource apk. Base-xxhdpi. Apk is an XXHDPI resource APK. The best thing about this type of APK is that they don’t have a dex file, and they have a unique split attribute in their manifest

Adb install Split APk

Once these two types of APK are unzipped, you can install them via ADB, using the following commands

Adb shell PM install-create adb shell PM install-create adb shell PM install-create Adb shell PM install-write {sessionId} base-zh.apk /data/local/ TMP /base-zh.apk adb shell PM install-write {sessionId} base-zh.apk /data/local/ TMP /base-zh.apk install-commit {sessionId}Copy the code

Here’s a complete example

adb shell pm install-create
#Success: Created Install Session [1237281889]
adb shell pm install-write  1237281889 base.apk /data/local/tmp/FeatureSplitBase.apk
adb shell pm install-write  1237281889 base1.apk /data/local/tmp/FeatureSplit1.apk
adb shell pm install-write  1237281889 base2.apk /data/local/tmp/FeatureSplit2.apk
adb shell pm install-commit 1237281889
Copy the code

/app_bundle_install.sh /app_bundle_install.sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh/app_bundLE_install. sh It will install all the APKs in the directory. Don’t get confused or the installation may fail

Split APK structure and installation process

The structure of a Split APk is simple, usually consisting of a base APk and one or more Split APks. Base.apk does not have a Split property, while Split apk has a Split property. This is the only way to distinguish between a base and a Split. Start with ADB shell PM install-create

adb shell pm install-create

Corresponding is to install this step – package in the Session is created, the adb shell PM finally are sent to the PackageManagerShellCommand. OnCommand () method of handling, Process is roughly the adb – > binder – > PackageManagerShellCommand, not very familiar with, for the adb’s side is no longer a careful study.

PackageManagerShellCommand.runInstallCreate()

  1. Gets the output stream to adb shell, which can be displayed directly in the console through ADB
  2. callmakeInstallParams()Create SessionParams,
  3. calldoCreateSession()Create a Session
  4. Output the sessionId to the console

PackageManagerShellCommand.makeInstallParams()

  1. Create the SessionParams object
  2. Create the InstallParams object
  3. According to theadb shell pm install-createThe SessionParams parameter specifies the SessionParams flag, for example:adb shell pm install-create -RYou can overwrite an existing application
  4. Returns the InstallParams object

PackageManagerShellCommand.doCreateSession()

  1. Determine for whom the application is installed. By default, all users are installed
  2. Obtain the PackageInstallerService through PkMS and call its createSession(), see the details
  3. Returns the sessionId

adb shell pm install-write

This step corresponds to the Session operation in the install application,

PackageManagerShellCommand.runInstallWrite()

  1. Obtain the following parameters of the shell command, including the size of the file, the sessionId, the name of the file to be installed in the system (data/data/app), the path (preferably in /data/local/ TMP), Because the owner must have access to both shell and system permissions)
  2. calldoWriteSplit()Copy the APK

PackageManagerShellCommand.doWriteSplit()

  1. Open the session that you created earlier, and the thing to note here is that it’s called onceadb shell pm install-writeWill be calledsession.open()Method, so to avoid creating stageDir more than once, there’s one heremPreparedProperties,see
  2. Reencapsulates a PackageInstaller.Session, but it doesn’t seem necessary
  3. Determine whether a stream is installed, where stream should meanadb installThis way, obviously this is not the way to install it
  4. callopenFileForSystem()Open the file and get the file descriptor
  5. callPackageInstaller.Session.write().seeNotice hereinComingFDIt’s on/data/local/tmpOf the apk

adb shell pm install-commit

PackageManagerShellCommand.runInstallCommit()

  1. The sessionId parameter is obtained
  2. calldoCommitSession()Send an installation request
  3. calldoWaitForStagedSessionReady()Handle some errors and wait for the session to complete

PackageManagerShellCommand.doCommitSession()

  1. callPackageInstallerService.openSession()In order to get the session
  2. Determine if the.dm and.apk names match. Dm is dex metadata, but I don’t know what it is
  3. Create LocalIntenReceiver to get the result of the installation
  4. callPackageInstallerSession.commit()To submit, see details
  5. callLocalIntenReceiver.getResult()Get the installation result. Note that this is a blocking queue that blocks until the application is installed
  6. Print the reason for successful installation or incorrect installation based on the result

conclusion

It is the same as clicking on adb to install an application, but it is possible to debug the app bundle using various flags. The other is the App Bundle. The principle of the app bundle is to install the resource APK and the code APK. The installation process is similar to that of normal APK, except that parse apK requires parse base. Apk, whereas app Bundle requires parse of all APK properties