And how I managed to fix the issue
Recently I was working on a Flutter app, that used Realm.io. And as expected quickly a very cool prototype was ready for testing. So I released app over Playstore’s internal test channel for test users. And as expected, unexpected happened!!
Suddenly found few of devices could not even start the application. Little more digging and I found out that devices with 64bit architecture were unable to run the application (x86_63 & arm64_v8a to be more specific).
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.codesphere.bol-2/base.apk"],nativeLibraryDirectories=[/data/app/com.codesphere.bol-2/lib/arm64, /data/app/com.codesphere.bol-2/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libflutter.so"
at java.lang.reflect.Method.invoke(Native Method)
When I viewed app’s apk file in Andorid Studio’s APK analyzer, I found in my application, I had used realm.io packages which had “librealm-jni.so” native library. And as we can see in the screenshot below, “libreal-jni.so” is present in all sub-folders of “lib”, for all the android device architectures. But, Flutter’s “libflutter.so” was only present under “armeabi-v7a” folder.
Little more RnD and from stackoverflow answer I came to know:
When the APK is installed, the installer checks if the package contains libraries in the official directories, and marks the activity as 32 or 64 bit depending on the outcome.
If it finds libraries in
lib/arm64-v8awithin the APK (normally taken from the directory
libs/arm64-v8ain the build directory), it will be marked as 64 bit, and will ignore all other directories. If it finds libraries in
lib/armeabiin the APK, the process is marked as 32 bit. If there's no native libraries in any of these, the installer assumes that the application doesn't use native code at all and is free to run it in either mode, in practice in 64 bit mode.
So, since my generated apk had folders for 64bit devices present, so installer marked it as 64bit app, and when running the app linker tried to find all the native libraries in 64bit flavored directories. And since it did not contain “libflutter.so” the above exception was thrown.
Reading much of discussions on flutter’s git issues pages, I realized that flutter is not shipping “libflutter.so” in 64bit mode (at least for now, may be the will provide it soon, as google promoting 64bit apps on stores). So few alternative options were suggested as building application with following command
flutter build apk --target-platform android-arm64
But, doing so gave me this apk structure:
Now, we have both “libflutter.so” and “librealm-jni.so” present under “arm64-v8a” folder but “armeabi-v7a” has only “librealm-jni.so” .
So, devices with 64bit architecture were able to run the app, but now 32bit devices were unable to run the application. :(
So, either we are going to generate two apk files targeted for 32bit & 64bit devices separately or we need to find another solution which should work for both type of architectures.
In the stackoverflow’s answer it says:
Yes, arm64-v8a devices can also run armeabi-v7a code.
So, if our apk has only “armeabi-v7a” libraries present and if we could stop generation of other architecture directories in our apk, both 32bit & 64bit devices would be able to run application.
Gradle provides a feature to select specific binary to package in generated apk
abiFilters:Specifies the Application Binary Interfaces (ABI) that Gradle should build outputs for and package with your APK.
Now using “abiFilters” option we can select only “armeabi-v7a” specific binaries to go in our generated apk with following configuration (shown in bold) in our ‘anroid/app/build.gradle’:
With this configuration, we are telling gradle to package libraries only for “armeabi-v7a” architecture. After adding this, generate apk using following command:
flutter build apk
Analyze the newly generated apk in your Android studio.
As seen in above screenshot, now apk contains only “armeabi-v7a” folder and none of other architecture specific folders, so running apk on 64bit device won’t find any folders for 64bit specific libraries, and installer will mark it as 32bit application and will look for libraries under “armeabi-v7a” folder, and it contains both the libraries required by app. :)
The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.