Android: including ndk .so libraries for different architectures, app crashes

2.7k Views Asked by At

I'm not new to Android development but I'm a total newbie when speaking about NDK and .so libraries.

The app I'm building uses third party SDKs and they provide some .so files. They provide me with an .so file for every architecture (so far: arm64-v8a, armeabi, armeabi-v7a, mips, mips64, x86, x86_64).

I need to include a new third party SDK but they only provide .so files for armeabi-v7a and x86. When I try to run my app, it crashes and I get an error from the SDK (I see it on logcat) that states:

SDKNAME currently only provides prebuilt library for armeabi-v7a and x86 architectures

Is this a common scenario ? is there a way to fix this kind of scenario ?

Thanks a lot in advance

2

There are 2 best solutions below

0
On BEST ANSWER

Store your compiled libraries in app/src/main/jniLibs/{arch} for example: armeabi/armeabi-v7a and then add the lines at the end of the post to your apps build.gradle.

The productFlavours is used to configure the compilation variants, so this way you could link properly already compiled libraries.

android.ndk {
        moduleName = "your_library_jni"
        cppFlags.add("-fexceptions")
        cppFlags.add("-std=c++11")
        cppFlags.add("-I" + file("src/main/jni").absolutePath)
        }

android.productFlavors {
        create("x86") {
            ndk.with{
                abiFilters.add("armeabi")

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi/"

                ldLibs.add(libsDir + "libyour_module.so")

            }
        }
        create("arm-v7a") {
            ndk.with {
                abiFilters.add("armeabi-v7a")

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi-v7a/"

                ldLibs.add(libsDir + "libyour_module.so")

            }
        }
    }
0
On

You need to have all libraries available for all architectures that your application will support.

When the APK is installed, the installer scans the APK for what architectures it supports. If an APK doesn't include native code, it supports all architectures. If it does include native code however, it only supports those architectures that are included in the APK. Most modern devices support more than one architecture; for example, a device might support arm64-v8a and armeabi-v7a, or x86_64 and x86, or x86 and armeabi-v7a (via emulation). On installation, it looks through which architectures are included, picks the most preferred architecture of those, and installs all libraries from that architecture, ignoring the rest. (Older Android versions may unintentionally have shown a slightly different, inconsistent behaviour in cases like the one described - see https://stackoverflow.com/a/25648943/3115956.)

Now if one of the libraries you include comes in builds for all available architectures, while another one only supports a few, the installer might pick e.g. arm64-v8a, and thus not get all the necessary libraries.

Thus, you can only support the intersection of architectures provided by all of your libraries.

To achieve this, you can either manually remove the excess directories from the SDKs that provide more architectures, or if using Gradle to build your APK, you can add this to a NDK block:

abiFilters 'armeabi-v7a', 'x86'