10

I'm publishing an app using the new app bundle format (aab). The app includes some native libraries for armeabi-v7a. When I install the app through Google Play on an arm64-v8a architecture it doesn't include native libraries for which there's no arm64-v8a so file.

According to this https://stackoverflow.com/a/39622499/534471, a armeabi-v7a library should run on an arm64-v8a device (and it works fine when installed through adb so it does work indeed).

The Google Play console shows the different apks by architecture, screen density etc. From the apk sizes I can clearly tell which ones don't include the native libraries. I also use a native libs monitor app to analyze the installed apk and it clearly doesn't include the native libraries I need (it includes arm64-v8a native libraries if the app has an arm64-v8a so file but not if there's only an armeabi-v7a version).

My gradle build file includes this small piece of code for bundle configuration:

    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
//            include 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }

Now here's my question: is there a way to tell the build tool to include the "next best" native library in each apk, next best being the closest version that would run on a specific architecture?

PS: If I set enableSplit = false for the abi then it will include the native library (as expected) but unfortunately for all platforms including x86 which alone is 20MB big...

For those who haven't seen how Google Play splits the app bundle into apks, here's a screenshot: enter image description here

Emanuel Moecklin
  • 28,488
  • 11
  • 69
  • 85

1 Answers1

7

There's no need to tell the tooling to serve the next best, that should be done automatically. If the device reports to also support armeabi-v7a, it should receive the APK that contains it.

Edit:

Given your screenshot, it seems that your app provides native libraries for the arm64-v8a architecture, so the arm64-v8a libraries will be served and not the armeabi-v7a ones.

Note also that one device is not able to load libraries from different architectures for the same app, i.e. you can't expect that some libraries be loaded in 64 bits and some others in 32 bits. Even with a "fat" APK containing all ABIs, the Android platform will only select one ABI upon installation of your app and discard all the other files, so from the moment you provide at least one library for arm64-v8a, none of the armeabi-v7a libraries will ever be loaded on an arm64-v8a device.

Edit:

You should consider excluding some ABIs from your app if you can't provide the required native libraries for that architecture. This can be achieved using the abiFilters block in the gradle config:

ndk { abiFilters 'armeabi-v7a', 'x86' }

Pierre
  • 15,865
  • 4
  • 36
  • 50
  • "There's no need to tell the tooling to serve the next best, that should be done automatically" -> that was my expectation. I'd assume it's a bug in Google Play because I can see the apks it creates for all splits and the one served to my device clearly has no native library in it. I'll contact their support. – Emanuel Moecklin Jun 29 '18 at 13:27
  • Concerning the ndkFilter. Google Play creates apks that include armeabi-v7a native libs but only for the apks that are served to armeabi-v7a devices. I added a screenshot to the question to make this clear. So no there's no abi filter or there would be no apks with armeabi-v7a native libs. – Emanuel Moecklin Jun 29 '18 at 14:03
  • I edited my answer based on your screenshot. I think it may just be a misconception that an app can load both a mix of 32 and 64 bits on one device? – Pierre Jun 30 '18 at 08:15
  • The apks served to arm64-v8a devices don't contain any native libraries. The aab file has only libraries for armeabi-v7a. What I expect is that Google Play creates apks for arm64-v8a devices including the armeabi-v7a library because that one will run on arm64-v8a as well. – Emanuel Moecklin Jul 01 '18 at 20:14
  • Based on the screenshot you provided, I believe you are mistaken that your AAB does not include any `arm64-v8a` libraries. Unzip the `.aab` that you uploaded and search for the existing of a directory named `base/lib/arm64-v8a`. You most likely depend on a library that includes a native library for that ABI. – Pierre Jul 01 '18 at 20:44
  • You can also run the following command to check what are the splits served by Play for your app on a connected device: `adb shell dumpsys package | grep splits`. Are you able to share the result of that command? – Pierre Jul 01 '18 at 20:47
  • The served apk does include an arm64-v8a library but not the one I need. The aab includes a x86 and an armeabi-v7a version of that particular native lib (it's OpenCV btw) and other native libraries for armeabi, armeabi-v7a, arm64-v8a, x86, x86_64 and mips/mips64. The split is: splits=[base, config.arm64_v8a, config.xxhdpi] – Emanuel Moecklin Jul 01 '18 at 22:15
  • Sorry for not being 100% clear. I changed the question to reflect the fact that the apks do include native libs if there's a arm64-v8a version of the lib in the app -> aab file but not if there's only a armeabi-v7a version of the native lib. – Emanuel Moecklin Jul 01 '18 at 22:24
  • As I tried to explain in my answer, the Android platform does not support mixing 32 and 64 bits libraries for a given app. You must either provide all the native libraries you need in 64 bits, or you need to provide none (removing them can be achieved using ndkFilter). In other words, you cannot provide half of the libraries in 32 bits and the other half in 64 bits and expect Play to serve a mix. Does that make sense? – Pierre Jul 01 '18 at 22:42
  • If I remove all the 64 bit libraries I can't deploy the app any more through adb on a 64 bit device. ADB tells me the device supports arm64 but the apk only supports armeabi, armeabi-v7a etc.. How would I solve this? – Emanuel Moecklin Jul 02 '18 at 03:09
  • You should be able to deploy without issue, What is the error message exactly? – Pierre Jul 02 '18 at 05:22
  • "device supports arm64-v8a but the apk only supports armeabi, armeabi-v7a, x86, mips", removed the 64 bit libraries using abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'mips', I can't really remove the 64 bit libraries otherwise since it's 3rd party libraries – Emanuel Moecklin Jul 02 '18 at 05:30
  • 1
    Ok so this works: ```ndk { abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'mips' }``` and ```abi { enableSplit = true }``` in the bundle configuration, deployed through Google Play, the 64 bit device receives the armeabi-v7a lib and everthing works, if you want to add that to your answer, I'll gladly accept it – Emanuel Moecklin Jul 02 '18 at 06:03
  • Ah, it was "abiFilters" not "ndkFilter", sorry for the confusion. I edited my answer to include the snippet. A few additional things to note though: * `abi { enableSplit = true }` is the default, thus redundant. * You should consider also excluding `armeabi` and `mips` since the OpenCV library is also not provided in those architectures. This will make your App Bundle smaller and will avoid issues on devices that would declare "armeabi" or "mips" as their primary supported architecture (as low as this number may be). – Pierre Jul 02 '18 at 10:01