Android App bundle install not placing native libs in the lib/$ABI folder

390 views Asked by At

In order to try and understand how Android App Bundles deploy native .so I created a simple test app using android studio.

  1. The test setup:

I added some test .so's.

enter image description here

Also added the necessary line to the app's build.gradle file

sourceSets {
    main {
        jniLibs.srcDirs = ['src/main/jniLibs']
    }
}
  1. Checked building and installing a apk works as expected.

I see the following files/folders in the root of the apk install

base.apk
lib
oat

the lib folder contains arm64 which contains

libexepython2.7.so
libffi.so

Note: I expected that bdiff.so would NOT be present as it doesn't following the required naming pattern of lib<name>.so

So this works as expected.

  1. Built Android App Bundle (AAB).

Examining the AAB

base
BUNDLE-METADATA
META_INF
BundleConfig.pb

The AAB/base folder contains

lib
native.pb
(and others...)

I see references to lib/arm64-v8a and lib/armeabi-v7a in the native.pb file.

The AAB/base/lib/ folder contains

arm64-v8a
armeabi-v7a

arm64-v8a contains

bdiff.so
libexepython2.7.so
libffi.so

So all seems reasonably sensible.

  1. Converted to .apks using bundletool

    java -jar bundletool.jar build-apks --bundle=release\app-release.aab --output=app.apks --overwrite

The apks archive contains a splits folder with base-arm64_v8a*.apk base-armeabi_v7a*.apk files.

Confirmed that base-arm64_v8a.zip contains a lib/arm64-v8a folder with

bdiff.so
libexepython2.7.so
libffi.so
  1. Installed via bundletool

    java -jar bundletool.jar install-apks --apks=app.apks

Looking at the install I see the following files/folders in the root of the apk install.

base.apk
lib
oat
split_config.arm64_v8a.apk
split_config.en.apk
split_config.xhdpi.apk

the lib folder contains arm64 which is empty!

Question: Why is the lib/arm64/ folder empty? Why isn't the app bundle installing .so's?

To rule out bundletool problems, I've also tested installing AAB with google 'internal app sharing' (with a different non test app), and observed similar results.

1

There are 1 answers

2
Tom On

Cause

From the gradle 3.3.0 release notes

When building an Android App Bundle, APKs generated from that app bundle that target Android 6.0 (API level 23) or higher now include uncompressed versions of your native libraries by default. This optimization avoids the need for the device to make a copy of the library and thus reduces the on-disk size of your app. If you'd rather disable this optimization, add the following to your gradle.properties file:

android.bundle.enableUncompressedNativeLibs = false

So in summary the cause was that for Android App Bundle (AAB) native libraries are not 'installed' by default, but rather uncompressed versions are included in the apk, which I guess the app is expected to somehow use.

Use compressed and installed native libs when using older Gradles

this answer suggested setting android.bundle.enableUncompressedNativeLibs=false in the gradle.properties.

Use compressed and installed native libs when using newer Gradles

Add the following to the android section of your apps build.gradle file

packagingOptions {
    jniLibs {
        useLegacyPackaging = false
    }
}

Use compressed and installed native libs when using Maui

To do the same when building Android apps with MAUI:

  1. Create a BundleConfig.json file:

    {
    "optimizations" : {
    "uncompress_native_libraries" : {}
    }
    }

  2. Add <AndroidBundleConfigurationFile>BundleConfig.json</AndroidBundleConfigurationFile> to your MAUI .csproj file.

Verifying the AAB is using compressed native libs

To tell if you AAB uses uncompressed native libraries, and therefore doesn't extract them on install, run the following command:

java -jar bundletool-all.jar dump config --bundle=myapp.aab

If the output contains

"uncompressNativeLibraries": {
"enabled": true
},

OR the output doesn't have uncompressNativeLibraries set, then the AAB uses uncompressed native libraries.

If you see

"uncompressNativeLibraries": {
},

then it uses compressed native libraries and will uncompress them and copy them on app install.