
こんにちは、アプリエンジニアの日野です。
今回は、実務でFlutterのメジャーバージョンを2から3にアップデート作業時に発生した問題とその対応方法について記載していきます。
背景
アップグレードを行う背景には、今回iOSのプライバシーマニフェスト対応を行う必要がありました。
Flutter自体もPrivacy Manifestを含める必要がありその対応が3.19から入るとのことでしたので、これを機にパッケージなども含めてアップグレードを行いました。
Flutter 2.10.1を使用していましたが、Flutter 3.19.3までアップグレードしました。
またiOSの他にAndroidでも展開していた為、iOS・Androidの2つのOSでアップグレード作業を行いました。
アップグレード時に発生した問題とその時の対応
一部ウィジェットでThemeがうまく適用されない
- YearPickerを使用していた箇所に対して独自のThemeを適用していましたが、その箇所にThemeが適用されなくなっておりデフォルトの背景色が固定で適用されてしまっていました。
- GridViewで自作することで対応しました。YearPickerの内部構造を調査をしましたが読み解くコストより自前で実装を進める方が少なく済む為、今回自作することを選択しました。
(iOS) パッケージのアップグレードによる Podfile のビルドエラー
pubspec.yamlでバージョンを更新後、Podfileで指定されているバージョンと合わなくなりビルドエラーが発生することがありました。- 出てきたエラーに互換性のあるバージョンが表示されていた為、そのバージョンに合うバージョンを指定しました。
(Android) パッケージのアップグレードによるGradleのビルドエラー
- build.gradleにて
compileSdkVersion等を更新する際に、Flutterのパッケージの影響でGradleでエラーが発生していました。 - Gradleのバージョンを手動で変えて対応しました。
- Android Studioにあるマイグレーションする機能を試してみましたが、うまくいかないケースがありましたので、手で変更しました。
- Androidでの開発を普段されない方は、Gradle、AGP(Android Gradle Plugin)、Android Studioのバージョンなど似たような用語が出てきますのでまずはそちらを確認されると良いと思います。
(iPad) シェアモーダルが表示されない
- バージョンをアップグレードをしたことで、iPadでのシェアモーダルが表示されないという問題がありました。
- 同様の事象が発生しているIssueがありまして、修正方法が記載されていたコードを参考に対応しました。
ダウンロード機能でクラッシュ
- ファイルをダウンロードする機能がありますが、バージョンアップグレードによってメソッドの引数に渡す型が変わっておりエラーが出ていました。
- 新しい引数の型に合うようにコードを修正しました。

修正時の差分 - 受け取る値の型がObjects?型でしたので、ビルドエラーなどもなく動作させるまでは気づきにくい箇所でした。
(Android) targetSdkVersionのアップグレードによる権限不足エラー
targetSdkVersionを34に変更したところ、フォアグラウンドサービスを使用する機能がクラッシュするようになっておりました。AndroidManifest.xmlに<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>を追記することで対応しました。
Privacy Manifestの対応見込みのないパッケージ
package_infoというパッケージを使用しておりましたが、リポジトリがPublic archiveになっており、Privacy Manifest対応がされる見込みがありませんでした。- 後継パッケージである
package_info_plusへの乗り換えを行いました。
Material Design 2の固定
- Flutter 3.16から
useMaterial3がデフォルトでtrueとなりました。(https://docs.flutter.dev/release/breaking-changes/material-3-default) - 今回の工数と影響範囲を考慮して今回はオプトアウトする方法を選択しました。
他にも、ルーティングのパッケージが破壊的変更によって各画面のアノテーションを変更したりやiOSの通知領域のフォントカラーが白色から黒色になっていたりと他にも細かい不具合はありましたが、地道に対応しました。
アップグレード時に問題が頻発しやすい箇所
今回アップグレードを行っていて、問題にぶつかることが多かった箇所について個人的な感覚を述べますと以下の順番となります。
- ネイティブ機能に近い箇所
- SNSシェア・通知領域・ファイルダウンロード等
Podfileやbuild.gradle、Info.plistやAndroidManifest.xml等のネイティブの設定ファイル- 特定のライブラリのバージョンを固定したい時や、OSバージョンをアップグレードする際に変更することがありました。
- UIに近い箇所
- こちらは今回そこまでアップグレード時も影響はあまりありませんでした。
- おそらくMaterial Design 2のままで進めている為、Material 3にした場合は、もう少し対応が必要になるかと思います。
結果、普段触ることがないファイル程、別途対応が必要なことが多い傾向がありました。
パッケージアップグレード作業時に押さえておくべきポイント
次回パッケージアップグレード作業が発生した場合、以下の点を押さえて着手することでインパクトを小さくしながらアップグレード作業が進められると感じました。
ネイティブ機能を使用するパッケージのアップグレード時は、Info.plistやAndroidManifest.xmlの権限が追加する必要がないかGitHubのIssueを確認しておく
- 権限不足のエラーはビルドエラーではなく実行時エラーになる為、発見が遅れるケースが多々あるかなと思います。
UIに関連するパッケージをアップグレードする際には、変更時の影響と未変更時の影響を比較して目的にあった方を選択する
- ナビゲーションに
auto_routeを使用しておりますが、破壊的変更がv6で入っており、その後v7,v8とバージョンが上がっており、ほぼ全画面のコードを変更する必要がありました。 - 影響範囲が広くクリティカルな問題がなければ、工数と相談してアップグレードしない選択を取るのも1つの方法だと思います。
Podfile や build.gradle 等のネイティブでのバージョン指定がある場合、どのバージョンが使用されているか確認する方法を押さえておく
- こちらは古いバージョンのまま動いている箇所を最新バージョンを使用していると勘違いしたまま確認をすることがある為、ライブラリのバージョンを確認する方法は押さえておくと良いと思います。
更新頻度が高いライブラリの場合、pod repo update 等、手元のパッケージ管理ツールの更新コマンドを押さえておくこと
- 余談ですが、Privacy Manifest対応時、数日頻度でライブラリが更新されており、
pod repo updateコマンドを叩かずpod installをしてしまい、新しいバージョンが取得できないということがありましたので記載しました。
GitHubのIssueやPRにてこの操作をした意図や参考にしたURLを残しておく
- これは未来のプロジェクトメンバーに対して当時の作業状況を残すために残しておくと良いかと思います。
今後試してみたい項目
ゴールデンテスト等のビジュアルリグレッションテストによるバグ検知の仕組み化
- バージョンアップ後も新機能の実装を行うと画面の一部レイアウトが変わることがあり、新しいUIを追加することで一部OSでレイアウトが崩れることがありました。
- レイアウト崩れを機械的に検出するために、ゴールデンテストなどのビジュアルリグレッションテストを導入していきたいと考えています。
月一間隔でパッケージのアップグレードができる開発の仕組み化
- 今回大きくメジャーアップグレードを行ったことで、影響範囲が広くほぼ全機能のテストを実施しました。
- 細かくアップグレードができる仕組みを作ることで、細かいバグ修正や機能追加が容易になりアプリのクオリティを保つことができると考えています。
まとめ
普段あまり行わないアップグレード作業ですが、担当者が変わっている場合もありアップグレード作業は難航ことがあるかと思います。 銀の弾丸はありませんでしたが、地道に動作確認と修正を繰り返すことでネイティブ機能の幅広い知見が得られましたので、今後も臆さずアップグレード作業に取り組んでいきたいと思います。