ここ最近、Flutterを使ってiOSとAndroidに両対応するアプリを作っています。具体的にはSkywayのサービスを使ってWebRTCするアプリなのですが、Android用にリリースビルドした場合だけ、起動後の特定のタイミングでアプリが落ちるという現象に遭遇しました。デバッグビルドでは問題ないので、リリースビルドにまつわる何かの設定が原因なのでしょうが・・・。
まず、リリースビルドしたアプリをインストールしたAndroid実機をUSBデバッグ接続した後で、flutter logs
を実行するとログを参照することができます。アプリが落ちた時点のログはこのようなものでした。
E/AndroidRuntime(26930): FATAL EXCEPTION: main
E/AndroidRuntime(26930): Process: (アプリ名), PID: 26930
E/AndroidRuntime(26930): java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/~~E9NZrxVI7LH3m6VpZEnsIQ==/jp.co.digi.digirtc-FOPlKt6zYS48sHJM96HXZw==/base.apk!/lib/arm64-v8a/libskyway.so"
E/AndroidRuntime(26930): at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
E/AndroidRuntime(26930): at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
E/AndroidRuntime(26930): at java.lang.System.loadLibrary(System.java:1664)
E/AndroidRuntime(26930): at io.skyway.Peer.Peer.<clinit>(Unknown Source:27)
E/AndroidRuntime(26930): at jp.co.digi.digirtc.MainActivity.X(Unknown Source:42)
E/AndroidRuntime(26930): at jp.co.digi.digirtc.MainActivity.O(Unknown Source:0)
E/AndroidRuntime(26930): at jp.co.digi.digirtc.MainActivity$c.h(Unknown Source:48)
E/AndroidRuntime(26930): at e.a.d.a.j$a.a(Unknown Source:17)
E/AndroidRuntime(26930): at io.flutter.embedding.engine.e.b.d(Unknown Source:57)
E/AndroidRuntime(26930): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(Unknown Source:4)
E/AndroidRuntime(26930): at android.os.MessageQueue.nativePollOnce(Native Method)
E/AndroidRuntime(26930): at android.os.MessageQueue.next(MessageQueue.java:338)
E/AndroidRuntime(26930): at android.os.Looper.loop(Looper.java:323)
E/AndroidRuntime(26930): at android.app.ActivityThread.main(ActivityThread.java:7710)
E/AndroidRuntime(26930): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(26930): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
E/AndroidRuntime(26930): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:954)
SkywayのPeerを取るあたりが怪しいことが分かります。エラーはUnsatisfiedLinkError
ということのようです。
原因はアプリの難読化
Skywayサポートでのこちらの問答とコメントを見ると、難読化処理が怪しそうだというヒントが得られました。
アプリの難読化については、こちらの公式ドキュメントが参考になります。
Flutterではデフォルトで難読化が有効
こちらの記事が解決策になりました。どうやら、Flutterでリリースビルドするとデフォルトで難読化が行われるようであり、そのためにデバッグビルドでは問題なく動作するけど、リリースビルドでは落ちるという違いになるわけですね。
Flutter+Skywayにおける解決策
上記の参考にさせていただいたサイトの情報をまとめると、このような解決策となりました。
android/app/build.gradle
に下記の内容を追記します。
android {
compileSdkVersion 30
(中略)
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
// ProGuardの設定ファイル(この部分を追記)
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
(中略)
}
(以下はskywayライブラリのインポート部分。android/app/lib/skyway-2.6.0.aarがある前提)
dependencies {
compile (name:'skyway-2.6.0', ext:'aar')
}
repositories {
flatDir {
dirs 'lib'
}
mavenCentral()
}
さらに、android/app/proguard-rules.pro
をプレーンファイルとして新規作成し、下記のとおり記述します。
-keep class io.skyway.** { *; }
これでリリースビルドをやり直すと、アプリが落ちることはなくなりました。