I have a few native libraries that are fairly big and bloating the application binary size. I looked into APK splitting but maintaining and QAing multiple APKs is not something
When I read @mstorsjo answer I was a little bit confused how to really use only one (or two) native libs, even though it's quite simple and straightforward. Therefore, I will give here an example and some more explanation (based on my further research).
For each supported architecture we have to create a specific folder in the jniLibs folder and drop the .so file there. As an example, for supporting armeabi-v7a (32bit) and arm64-v8a (64bit):
|--app
|--|--src
|--|--|--main
|--|--|--|--jniLibs
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--arm64-v8a
|--|--|--|--|--|--.so Files
With armeabi-v7a you support more than 90% of the available devices, but since it is 32bit architecture, running it on 64bit devices will result in an loss of performance (20-30%) {1}. For each specific case it can be quite handy to check the actual amount of supported devices, which can be done within the Google Play Console in the Release management > Device catalog section, by specifying ABI as filter.
When you don't add binaries for all architectures you have to be aware of the following:
If your app contains any other native libraries, you'll have to make sure you only have the same versions of them as well. That is due to Android demanding that all loaded native libraries be built for the same architecture. For example, if the first native library loaded is armeabi-v7a, Android will look ONLY for armeabi-v7a libraries on all System.loadLibrary() calls after that. If it doesn't find that exact architecture, it'll throw the java.lang.UnsatisfiedLinkError exception. {1}
I ran into this problem because some of my dependencies used native libraries, whereby armeabi-v7a couldn't be loaded anymore.