Flutterで開発したアプリがAndroidでリリースビルドの場合だけ落ちる場合の対応

ここ最近、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.** { *; }

これでリリースビルドをやり直すと、アプリが落ちることはなくなりました。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。画像認識モデルを活用したアプリや、生成AIを業務に組み込むためのサービス「Gen2Go」の開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。