Flutter 运行报错:couldn't find "libflutter.so"
今天从新打开去年自己写的一个Flutter项目,发现编译都通过了,直接真机运行就报错如下:
2021-02-26 14:17:49.769 875-875/? E/.huan.io.penci: Unknown bits set in runtime_flags: 0x8000
2021-02-26 14:17:50.117 875-875/com.huan.io.pencil E/libc: Access denied finding property "ro.vendor.df.effect.conflict"
2021-02-26 14:17:50.131 875-875/com.huan.io.pencil E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.huan.io.pencil, PID: 875
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.huan.io.pencil-41DS1J9twqdDM4BlnXuyew==/base.apk"],nativeLibraryDirectories=[/data/app/com.huan.io.pencil-41DS1J9twqdDM4BlnXuyew==/lib/arm, /data/app/com.huan.io.pencil-41DS1J9twqdDM4BlnXuyew==/base.apk!/lib/armeabi-v7a, /system/lib, /system/product/lib]]] couldn't find "libflutter.so"
2021-02-26 14:17:50.143 875-875/com.huan.io.pencil E/MQSEventManagerDelegate: failed to get MQSService.
分析:
我们挑重点可以看第五行和第六行,意思就是说找不到libflutter.so包。那么这个so包是什么包呢,在开发中,android的原生代码一般使用C、C++编写,然后编译生成一个动态链接库,就是文件后缀为.so的ELF文件。写过jin的同学都知道,我们编写C或者C++
代码到最会编译运行阶段都是会编译成so包的形式供java调用,那么这个libflutter.so就是flutter编译之后的so文件了。
查找原因1:
这里还有一个重点,市面上的android 手机的底层都是linux 系统的,而每个手机的cpu架构是不一样的,大概分为:armeabi、armeabi-v7a、arm64-v8a、x86等,详细的大家可以自行去了解。而我们的flutter的编译系统只提供了4中CPU架构的so库,armeabi-v7a、arm64-v8a、x86和x86-64,意思就是说flutter在编译运行的时候可以生产这4个cpu架构的so包。而我们在打debug包的时候,系统默认是会把4个架构的包都打出来的,又因为我们在项目当中运用了我们自己编译的so包,而且这个so包子提供了armeabi-v7a 架构的,所以我们在app的build文件中设置的整个app的ndk 编译架构只有armeabi-v7a,入下:
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.huan.io.pencil"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
//选择要添加的对应cpu类型的.so库。
abiFilters 'armeabi-v7a'
}
}
这样就可以指定编译出来的flutter so 包是armeabi-v7a架构的了,一开始我就以为到这里应该就是没问题的了,但是直接运行真机的时候就报了上面的错了。查看了apk文件,打开armeabi-v7a发现,确实没有flutter.so文件,这又是为什么呢,应该会有才对的啊?
查找原因2:
既然这样都不行的话,我们直接来看一下flutter是怎么打包的吧。我们直接在Terminal 窗口直接运行flutter build apk,如下:
我们可以看到打包命令中我们可以配置一个叫做--target-platform 的参数,这个参数就是配置打包的cpu架构的,那这几个参数分别又是代表什么呢,我们打开D:\flutterInstallDir\flutter\packages\flutter_tools\gradle\flutter.gradle:
可以看到android-arm就是对应的 armeabi-v7a 架构,找到原因了,那么我们直接运行 :flutter build apk --target-platform android-arm 就可以打出正式包了。
解决方法:
那我们怎么设置打Debug包呢? 我们打开app 模块的build.gradle 文件,在apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 之前告诉打包任务我们要配置的打包架构平台。在文件中加入:
project.setProperty('target-platform', 'android-arm')
这样就可以直接Debug运行了。
结果:
打正式包:flutter build apk --target-platform android-arm
打Debug包:app的build.gradle模块加入project.setProperty('target-platform', 'android-arm')