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
- Why use AppBundle
- The use of AppBundle
- 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:
- Android Studio, make sure Android Studio version is greater than 3.2 and Gradle version is not less than 3.2.1
- 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
- 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
- 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()
- Gets the output stream to adb shell, which can be displayed directly in the console through ADB
- call
makeInstallParams()
Create SessionParams, - call
doCreateSession()
Create a Session - Output the sessionId to the console
PackageManagerShellCommand.makeInstallParams()
- Create the SessionParams object
- Create the InstallParams object
- According to the
adb shell pm install-create
The SessionParams parameter specifies the SessionParams flag, for example:adb shell pm install-create -R
You can overwrite an existing application - Returns the InstallParams object
PackageManagerShellCommand.doCreateSession()
- Determine for whom the application is installed. By default, all users are installed
- Obtain the PackageInstallerService through PkMS and call its createSession(), see the details
- Returns the sessionId
adb shell pm install-write
This step corresponds to the Session operation in the install application,
PackageManagerShellCommand.runInstallWrite()
- 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)
- call
doWriteSplit()
Copy the APK
PackageManagerShellCommand.doWriteSplit()
- Open the session that you created earlier, and the thing to note here is that it’s called once
adb shell pm install-write
Will be calledsession.open()
Method, so to avoid creating stageDir more than once, there’s one heremPrepared
Properties,see - Reencapsulates a PackageInstaller.Session, but it doesn’t seem necessary
- Determine whether a stream is installed, where stream should mean
adb install
This way, obviously this is not the way to install it - call
openFileForSystem()
Open the file and get the file descriptor - call
PackageInstaller.Session.write()
.seeNotice hereinComingFD
It’s on/data/local/tmp
Of the apk
adb shell pm install-commit
PackageManagerShellCommand.runInstallCommit()
- The sessionId parameter is obtained
- call
doCommitSession()
Send an installation request - call
doWaitForStagedSessionReady()
Handle some errors and wait for the session to complete
PackageManagerShellCommand.doCommitSession()
- call
PackageInstallerService.openSession()
In order to get the session - Determine if the.dm and.apk names match. Dm is dex metadata, but I don’t know what it is
- Create LocalIntenReceiver to get the result of the installation
- call
PackageInstallerSession.commit()
To submit, see details - call
LocalIntenReceiver.getResult()
Get the installation result. Note that this is a blocking queue that blocks until the application is installed - 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