【Flutter】Android12~とそれ以前でスプラッシュを出し分ける
Androidの実装経験のない自分が、Flutter製の個人アプリで掲題の対応をしたときに結構詰まったので、記事にまとめました。
前提
Flutter Engineの初期化前にネイティブのスプラッシュが表示されます。そこはネイティブの領域なので、ネイティブ側で編集する必要があります。
公式ドキュメント
Android版のスプラッシュ実装
AndroidはAndroid11以前と12以降で挙動が全く違います。
- ~Android11は、コードなりxmlをいじって自前でスプラッシュ画面を実装する必要あり
- Android12~は、android側で自動でスプラッシュ画面が表示されます
そのため自前でスプラッシュ実装をしている場合、Android12でスプラッシュが2重に出てしまいます。
スプラッシュの実装を消して、~Android11はスプラッシュを表示しない実装でも良いですが、Flutter Engineの初期化までをシームレスに繋げたいためスプラッシュは実装したい。
そうなるとスプラッシュの出し分けが必要になってきます。
Android12~とそれ以前でスプラッシュを出し分ける方法
Androidはバージョン指定のテーマを作成でき、下記のようにテーマを出し分けることができます。
公式ドキュメント
res/values/styles.xml # themes for all versions
res/values-v31/styles.xml # themes for API level 31+ only
この場合、全てのバージョンでstyles.xml
のテーマが反映され、API level 31~ (Android12~)はvalues-v31/styles.xmlのテーマが反映されます。
これを使ってスプラッシュの出しわけをします。(スタイルを継承することも可能。詳しくはドキュメント参照)
Flutterのプロジェクトを作ると自動で最低限必要なスタイルの指定がres/values/styles.xml
に指定されており、AndroidManifest.xmlで参照するところまで準備できているので、これを出し分けます。
<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
~Android11の場合
自前のスプラッシュを表示
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- アプリ起動時のテーマ -->
<!-- @drawable/splashに作った自前のスプラッシュを指定 -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@drawable/splash</item>
</style>
<!-- Flutter UI初期化まで表示されるテーマ -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
Android12~の場合
スプラッシュの背景色などの指定をする
Themeの指定で、背景色, 真ん中に表示されるアイコン, スプラッシュが表示されるduration程度なら指定できます。スプラッシュ表示自体をOFFにすることはできないようです。
公式ドキュメント
res/values-v31/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- アプリ起動時のテーマ -->
<!-- スプラッシュの背景色などを指定 -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowFullscreen">false</item>
<item name="android:windowSplashScreenBackground">@color/launch_background</item>
</style>
<!-- Flutter UI初期化まで表示されるテーマ -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
完成
~Android11
Android12~
【Flutter2.5~】io.flutter.embedding.android.SplashScreenDrawableはDeprecatedになった
スプラッシュが表示されて、FlutterのFrameが初期化されるまでの間を描画するためにio.flutter.embedding.android.SplashScreenDrawable
の指定がAndroidManifest.xmlにプリセットされていますが、Flutter2.5からは自動でAndroidの起動画面をキープしてくれるようになったので、削除して問題ないです。
Migrating from Manifest / Activity defined custom splash screens
余談
flutter_native_splashというスプラッシュのネイティブ実装をジェネレートしてくれる便利パッケージも存在しますが、あまり依存するパッケージを増やしたくなく、弊アプリでは自前で実装しました。
(実装は大いに参考にしました。:pray:)
Discussion