Reproduce

Add abiFilters to android/app/build.gradle :

1
2
3
4
5
6
7
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a'
}
}
}

Run command:

1
$ flutter run

Flutter app crashed by java.lang.UnsatisfiedLinkError:

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/xxxx/base.apk”],nativeLibraryDirectories=[/data/app/xxxx/lib/arm, /data/app/xxxx/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib, /product/lib]]] couldn’t find “libflutter.so”
at java.lang.Runtime.loadLibrary0(Runtime.java:1011)
at java.lang.System.loadLibrary(System.java:1660)
at io.flutter.view.FlutterMain.startInitialization(FlutterMain.java:156)
at io.flutter.view.FlutterMain.startInitialization(FlutterMain.java:133)
at io.flutter.app.FlutterApplication.onCreate(FlutterApplication.java:22)

As you can see, flutter run seems like forgot to put “libflutter.so” into apk.

Why?

Run command for log details flutter run —verbose, and then following logs show me the reason:


[ +7 ms] Building APK
[ +17 ms] Running Gradle task ‘assembleDebug’…
[ +1 ms] executing: [/flutter/] /flutter/android/gradlew -Pverbose=true -Ptarget=/flutter/lib/main.dart

-Ptrack-widget-creation=false -Pcompilation-trace-file=compilation.txt -Ptarget-platform=android-arm64 assembleDebug

Flutter detected my Android phone is arm64 device, so it executes gradle task assembleDebug with -Ptarget-platform=android-arm64.

And flutter.gradle ($flutterRoot/packages/flutter_tools/gradle/flutter.gradle) will take this property to find flutter engine prebuilt binary output which named flutter.jar :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
String targetArch = 'arm'
if (project.hasProperty('target-platform') &&
project.property('target-platform') == 'android-arm64') {
targetArch = 'arm64'
}
debugFlutterJar = baseEnginePath.resolve("android-${targetArch}").resolve("flutter.jar").toFile()
profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile()
releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile()
dynamicProfileFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-profile").resolve("flutter.jar").toFile()
dynamicReleaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-release").resolve("flutter.jar").toFile()
...
// Add x86/x86_64 native library. Debug mode only, for now.
flutterX86Jar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/flutter-x86.jar")
Task flutterX86JarTask = project.tasks.create("${flutterBuildPrefix}X86Jar", Jar) {
destinationDir flutterX86Jar.parentFile
archiveName flutterX86Jar.name
from("${flutterRoot}/bin/cache/artifacts/engine/android-x86/libflutter.so") {
into "lib/x86"
}
from("${flutterRoot}/bin/cache/artifacts/engine/android-x64/libflutter.so") {
into "lib/x86_64"
}
}
// Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones
// added after applying the Flutter plugin.
project.android.buildTypes.each { addFlutterJarApiDependency(project, it, flutterX86JarTask) }
project.android.buildTypes.whenObjectAdded { addFlutterJarApiDependency(project, it, flutterX86JarTask) }
...

Solution

Run with specified target-platform to workaround (flutter version < v1.5.x):

1
$ flutter run --target-platform=android-arm

And, furthermore, the option target-platform has been removed when updated to v1.7.x. (see #34369 )

In this case, You can run build apk before run :

1
2
$ flutter build apk --debug --target-platform=android-arm
$ flutter run --use-application-binary=build/app/outputs/apk/debug/app-debug.apk