Manually installing split APK files (App Bundles) via ADB
Can't really recommend doing it this way, but sometimes you have no other choice.
Ok, you got an Android app, but it’s split into several APK files, so as a result, it won’t install like a traditional APK. What do you do?
You are dealing with an App Bundle. The idea here (supposedly) is to reduce the APK size by splitting the app into several modules and only downloading those that apply to the device in question (e.g. a small screen device doesn’t need the graphic assets for a large screen device and vice versa). An “accidental” side effect of this is that sideloading such apps becomes next to impossible for the layman.
With App Bundles, the individual modules have no knowledge of each other (well, actually they have, but not in a way that’s useful for discovery). So, when you tap a split APK file in your notification shade, the Android system will know that you are trying to install something, but have no idea which, if any, other files need to also be included in the process. In other words, you end up with a partially installed app that crashes on startup.
Preparing for a manual installation
First copy all the split APK files, you need, to your device. The correct path for putting them is /data/local/tmp . However, that’s not a requirement. The rest of this post will assume them to be in your Download folder instead.
Using the commandline, start ADB and open a shell on your device:
Change to your Download folder:
Here you need a list of all the files, the app consists of as well as their respective sizes:
Write down the exact names and sizes of all the files, belonging to your app.
Performing a manual installation
The instructions below are given for stock Android pre Nougat. The syntax got changed eventually. For later Android versions, the space between the install keyword and the first option must be removed.
Open an installation session:
pm install -create -S TOTAL_SIZE_OF_ALL_APKS
A session ID will be printed. Now each split APKs must be staged individually, beginning with the base APK (actually the order doesn’t matter) at index 0:
pm install -write -S APK_SIZE SESSION_ID INDEX PATH
Once all files are staged, commit the installation, using:
pm install -commit SESSION_ID
Note: sessions do not consume space in the filesystem. They will also eventually expire when not committed. You can explicitly delete or just abandon them. The system is designed with app downloads breaking (e.g. due to connectivity loss) in mind, so it will automatically clean up after some time.
Let’s assume an app com.example.app with version code 42, consisting of the base APK, a language and a large screen module:
ls -l com.example.* -rw-rw-r-- root sdcard_rw 12345 2018-04-20 02:49 com.example.app-42.apk -rw-rw-r-- root sdcard_rw 67890 2017-04-29 04:06 com.example.app-42_config.en.apk -rw-rw-r-- root sdcard_rw 11233 2019-11-08 16:43 com.example.app-42_config.xhdpi.apk
The total size is 91468 bytes.
pm install -create -S 91468 4711
The session ID is 4711. Stage all three files:
pm install -write -S 12345 4711 0 com.example.app-42.apk pm install -write -S 67890 4711 1 com.example.app-42_config.en.apk pm install -write -S 11233 4711 2 com.example.app-42_config.xhdpi.apk
Commit for installation:
pm install -commit 4711
Congrats, you should now be able to use the app.