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?

The problem

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.

There's no way, Google had ulterior motives when coming up with the App Bundle format

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:

adb shell

Change to your Download folder:

cd /sdcard/Download

Here you need a list of all the files, the app consists of as well as their respective sizes:

ls -l

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.

Example

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.