はじめに
FlutterでAndroid開発中に特定のライブラリを導入すると、ビルドは通るのにアプリ起動時にこんなエラーで強制終了することがあるかもしれません。
couldn't find "libflutter.so"
at java.lang.Runtime.loadLibrary0(Runtime.java:1011)
at java.lang.System.loadLibrary(System.java:1657)
要はFlutterのライブラリが見つからない、ということですが、これはFlutterに限らずですが、JNIを使ったライブラリを取り込むときに注意する点です。
原因
Flutterはネイティブライブラリであるsoファイルとしてアプリ上で動作します。その際、別のライブラリでもネイティブライブラリを使っていた場合、必要なsoファイルがapk内に取り込まれずに強制終了しています。
順を追って説明していきます。
Flutterから生成されるsoファイル
まず他のライブラリを入れる前の状態でアプリをビルドしてapkの中身を見ると以下のようになっています。
このように3つのディレクトリにそれぞれlibflutter.so
が配置されています。
2019/1/17 修正:
flutterの現時点の最新1.1.9では、armeabi-v7aのサポートが終了し、arm64-v8aへ以降したため、記述を変更しました。キャプチャは古いままですのでご注意ください。(すみません、詳細確認中です)
- arm64-v8a
- x86
- x86_64
それぞれの詳細については公式参照:ABI管理
他のライブラリを入れた場合
私の場合、Google VR SDKを導入したため発生しました。
Google VR SDKの場合、下記の3つが用意されていました。
- arm64-v8a
- armeabi-v7a
- x86
参考:https://github.com/googlevr/gvr-android-sdk/blob/master/samples/ndk-hellovr/build.gradle#L47
その結果、lib配下には4つのディレクトリが生成され、それぞれの構成は以下のようになりました
- arm64-v8a
- Flutter(libflutter.so)
- Google VR(libgvr.so, liboanorenderer.so)
- armebi-v7a
- Google VR(libgvr.so, liboanorenderer.so)のみ
- x86
- Flutter(libflutter.so)
- Google VR(libgvr.so, liboanorenderer.so)
- x86_64
- Flutter(libflutter.so)のみ
何が起こるのか?
lib配下のsoファイルは、端末のハードによってどのディレクトリが使用されるか決まります。今回の場合、armebi-v7aとx86であれば両方のsoファイルが格納されているため、問題なく起動できます。
一方、arm64-v8aやx86_64を使用する端末で起動した場合どうなるでしょう?ディレクトリ内に必要なsoファイルが揃っていないため、loadLibrary
時にcouldn't find
と言われてしまうわけです。
どうすれば良いのか?
結論からいうと、gradleでabiFilter
を指定する必要があります。
android {
...
defaultConfig {
...
ndk {
// Specifies the ABI configurations of your native libraries Gradle should build and package with your APK.
abiFilters "x86", "arm64-v8a"
}
}
...
}
今回の場合、Google VRとFlutter両方が用意されているのは、x86とarmebi-v7aの二つのみなので、その二つをabiFiltersで指定します。
これにより、apkに取り込まれるsoファイルはabiFiltersで指定されたx86とarmebi-v7aのみとなり、それ以外のx86_64およびarm64-v8aはディレクトリが生成されなくなります。
まとめ
Flutterもネイティブライブラリを使用していることを忘れずに、soファイルが見つからないと強制終了した場合はabiFilterの見直しを検討してみてください。
また、クラッシュは端末のハードに依存するため、Play Consoleのリリース前レポートを利用して確認しておくのがよいかと思います。