Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Flutter][Add-to-app] デバッグビルドしたapk内のlibflutter.soが壊れる問題と回避方法

問題

Kotlinで実装されている既存アプリにFlutterを追加した所、デバッグビルドしたapkを端末にインストールできないことが起きるようになった。頻度は10回に1回くらい。

エラー発生時のlogcatの抜粋
2020-12-01 16:09:54.960 1578-2005/? W/ziparchive: Zip: inflate zerr=-3 (nIn=0xb40000787007ebda aIn=25638 nOut=0xb40000787006ebc0 aOut=24608)
2020-12-01 16:09:54.960 1578-2005/? W/zipro: ExtractToMemory failed with Zlib error
2020-12-01 16:09:54.960 1578-2005/? E/NativeLibraryHelper: Failed uncompressing libflutter.so to /data/app/vmdl854882831.tmp/lib/arm64/tmp.hVakYp
...
    --------- beginning of system
2020-12-01 16:09:54.961 1578-2005/? W/NativeHelper: Failure copying native libraries [errorCode=-18]

原因

apkのビルド時にlibflutter.soを圧縮しているが、それが正常できないのが原因。
問題が起きる時のapkからlibflutter.soを取り出してみると、サイズが約200KBになっている。libflutter.soは、正常時なら10MB以上ある。

回避策

libflutter.soの圧縮に問題があるので、libflutter.soの圧縮をしないことで問題は回避できる模様。
AndroidManifestのextractNativeLibsにfalseを設定することで、実現できる1

<manifest>
    <application
        android:extractNativeLibs="false" >
        ...
    </application>
</manifest>

ただし、libflutter.soを圧縮しなくなる分、アプリのサイズは増大するので注意。
問題が起きていたアプリでは、サイズが120MBから230MBに増えた。
基本、Wifi環境下でしかダウンロードしないのでよいが、そうでないなら、別の対処を考えた方が良い。
同じアプリでも、aabをReleaseビルドする場合は問題が起きたことがない。なので、デバッグビルド固有の設定に問題がありそうである。

補足

原因詳細

エラーログの「Zip: inflate zerr=-3」の部分に着目。エラーコードの定義箇所を見ると、 kInvalidFileというエラーで、意味は「入力ファイルを zip アーカイブとして処理できません。通常、小さすぎたり、大きすぎたり、有効な署名がないために処理できません」。

ということでlibflutter.soが破損しているということが分かる。

問題が起きるとき、MacのFinderからそのapkファイルを解凍しようとするとエラーが起きるので、Android OSの解凍処理には問題ないことが分かる。shellのunzipコマンドならapkファイルの解凍できる。解凍後、libflutter.soのサイズを見ると、約200KBになっていることが分かる。

Firebase Test Labでのエラーの見え方

この問題に気づいたのは、CIでFlutte入りのアプリをデバッグビルドし、Firebase Test LabでE2Eテストを実行しようとしたとき。
「The app APK is not a valid Android application.」というエラーが表示される。
以下、エラーログを示す[^2]。

sudo gcloud firebase test android run \
  --app "${DEBUG_APP_APK_PATH}" \
  --test "${TEST_APK_PATH}" \
  --test-targets "user bot2" \
  --device model=NexusLowRes,version=28 \
  --use-orchestrator \
  --environment-variables clearPackageData=true,coverage=true,coverageFile="/sdcard/coverage.ec" \
  --directories-to-pull /sdcard \
  --results-bucket ${TEST_RESULTS_BUCKET}

Have questions, feedback, or issues? Get support by visiting:
  https://firebase.google.com/support/

Uploading [app/build/outputs/apk/*******/debug/app-*******-debug.apk] to Firebase Test Lab...
Uploading [app/build/outputs/apk/androidTest/*******/debug/app-*******-debug-androidTest.apk] to Firebase Test Lab...
Raw results will be stored in your GCS bucket at [https://console.*******ers.google.com/storage/browser/*****************************/2020-12-01_04:15:54.367295_CwcV/]

Test [matrix-2dcbutvhf7ld6] has been created in the Google Cloud.
Firebase Test Lab will execute your instrumentation test on 1 device(s).
ERROR: (gcloud.firebase.test.android.run) 
Matrix [matrix-2dcbutvhf7ld6] failed during validation: The app APK is not a valid Android application.

Exited with code exit status 1
CircleCI received exit code 1

  1. 英語のリファレンスを読むと、Android Gradle Plugin 3.6.0以上だとデフォルトfalseとのこと。ただ、問題のアプリはextractNativeLibsの設定に対応していないAndroid 4.4が最小サポートOSのせいか、trueの動作になっていた。 

zigenin
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away