FlutterでAndroidのDeeplinkを実装するときはLaunchModeを頭の片隅に
はじめに
こんにちは。お世話になっております。スペースマーケットでAndroid/Flutterエンジニアをしておりますseoと申します。
今日は、Flutter開発しているときに、ちょっぴり必要になってくるAndroidネイティブの知識をシェアできればと思います。
「アプリ開発はFlutterから始めました」という駆け出しエンジニアの方々も多いと思いますので、そういう方向けの記事です。
ハマったこと
FlutterでDeeplinkの実装をしていたときに、ハマってしまいました。
状況としては、開発中のアプリから認証や決済系などの外部アプリへ遷移させて、操作が完了したら再びこちらのアプリへDeeplink経由で戻ってきてもらうような、ユーザーがアプリ間をまたぐ操作を実装するときです。
MyApp --(外部アプリ遷移)--> 外部アプリで操作 --(Deeplink経由)--> MyApp
想定されるユースケースとしては、
MyAppでユーザーが情報を入力し、外部アプリで本人認証や決済を行い、
deeplinkで再びMyAppに戻ると、ユーザーがせっかく入力した情報などが
リセットされてしまっていて、期待した動作にならない。といったことがあります。
解決法
FlutterプロジェクトのAndroid配下に下記のようなManifestファイルがあるかと思います。
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop" <<<<<<<<<<<こちらに注目
android:theme="@style/LaunchTheme"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="schemeName"
android:host="hostName" />
</intent-filter>
</activity>
着目してほしいのはandroid:launchMode="singleTop"
です。
Flutterプロジェクトを新規に作成したとき、こちらがデフォルトでsingleTop
に設定されているかと思います。
この状態だと外部アプリで操作後、deeplinkで元のアプリへ戻ってきた時に、初期画面に戻っていることがあります。
そんなときはこちらを試してみてください。
<activity
android:name=".MainActivity"
android:exported="true"
+ android:launchMode="singleTop"
- android:launchMode="singleInstance"
android:theme="@style/LaunchTheme"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="schemeName"
android:host="hostName" />
</intent-filter>
</activity>
AndroidのLaunchModeについて
今回なぜsingleTop
のままだと、なぜ入力していた情報などがリセットされるのか?
LaunchModeに関してはGoogle Developerのドキュメントを読んでみると、
An activity with the "standard" or "singleTop" launch mode can be instantiated multiple times.
と記載がある通り、singleTop
だと新たなインスタンスが作成される、つまり新たなActivityが起動していることになります。
A "singleInstance" activity, on the other hand, permits no other activities to be part of its task. It must be the only activity in the task.
それに対して、singleInstance
はその名から推測できる通り、単一のインスタンスのため、すでに存在しているactivityが使い回されることになります。
注意点としては、singleInstance
はnot recommended for general use
と記載がある通り、推奨される使い方ではないため、外部から呼び出される操作のときに、副作用がないかを検討する必要があります。
解決方法から得た学び
Flutter実装中に、iOSは問題なく期待通りの動作なので、Androidではうまく動かない(逆も然り)といった状況に遭遇したときは、Flutterのドキュメントだけでなく、iOS/Androidそれぞれの公式ドキュメントを見るようにすることが必要だと気づきになりました。
FlutterならiOS/Androidを一気に作れるので、学習することが少ないと一般的に言われますが、
こういったときにネイティブ実装の知識や経験が活きたりするので、普段から情報感度を高くしておくことも重要ですね!
最後に
スペースマーケットでは一緒に働く仲間を募集しています!
カジュアルに話を聞きたいだけという方でも大歓迎ですので、ちょっとでも興味があれば以下からご応募お待ちしております!
▼インフラエンジニア
▼Webエンジニア
▼アプリシニアエンジニア(EM候補)
▼バックエンドエンジニア(EM候補)
▼エンジニア採用ページ(迷ったらこちらからどうぞ!)
スペースを簡単に貸し借りできるサービス「スペースマーケット」のエンジニアによる公式ブログです。 弊社採用技術スタックはこちら -> whatweuse.dev/company/spacemarket
Discussion