Flutterのwebviewについて、とCookieの永続化
Flutter webviewを利用する機会があったので記録しておきます。iOS、Androidのそれぞれの仕様が異なるため、複雑になっています。
Flutter webviewとは
Flutterにおけるwebviewは本来、ブラウザで閲覧できるサイトをアプリ内で閲覧できるようにするものです。これによって、アプリから簡単にセッションなどを維持し、WEBアプリで実装された機能を利用できます。
ユースケース
- ネイティブアプリの画面の開発は最小限にして、必要な際にはWEBアプリの機能を使用する。
- 端末管理などの関係で、ネイティブアプリが必要だが、開発コストが高いのでWEBアプリの機能をまるごと利用する。
- 決済、認証などでサードパーティのものを使用するために本来ブラウザで閲覧するものを埋め込んで利用する。
flutter_webviewとinapp_webview
Flutterには純正のflutter_webviewと、サードパーティーのflutter_inapp_webviewが存在します。
後者の方が高機能で使いやすいですが、かなりバグが多いようです。
今回、はアプリ終了時のCookieの保存(永続化)と埋め込んだサイトのJavaScriptのCookieアクセスについて実際に動かしてみたのでその結果をまとめます。
検証環境
ソフトウェア | webview |
---|---|
flutter | 3.6.2 |
webview | 4.10.0 |
inapp_webview | 6.0.0 |
dotenv | 5.2.1 |
Android | 14.3 |
iOS | 17.5 |
サイトのJavaScriptのCookieアクセス
OS | webview | inappwebview |
---|---|---|
Android | 不可能 | 可能 |
iOS | 可能 | 可能 |
AndroidのwebviewにおいてはJavScriptからDartへの通信が制限されていると考えられます。
アプリ再起動時のCookie保持
OS | webview | inappwebview |
---|---|---|
Android | 保持 | 保持 |
iOS | 非保持 | 非保持 |
iOSにおけるCookie保持(永続化)
検証結果からわかる通り、iOSではサイトの Cookie情報が保持できません。ログインなどで Cookieを利用する際にはどのようにすればいいでしょうか?
Cookieを取得
webview、inappwebviewどちらにも CookieManagerという機能が存在し、アプリからサイトのCookie情報にアクセスできます。まずはこれを利用してアプリ側でCookie情報を扱えるようにします。
CookieManager cookieManager = CookieManager.instance();
Object obj = await cookieManager.getCookie(
url: WebUri("https://example.com"),
name: "{Cookiename}",
) ?? "";
Cookie data = obj as Cookie;
Cookieをストレージへ保存
取得したCookieは本体に保存する必要があります。shared_preferencesが利用されるケースが多いようですが、セッショントークンなどの機密情報の高い情報ではどうでしようか?
そこで、secure_storageを利用します。このデータは暗号化して保存されます。
データはKey:Valueの形で保存されます。
final storage = FlutterSecureStorage();
await storage.write(
key: "{Keyname}",
value: {Cookievalue},
);
Cookieをストレージから取得
Key:Valueで保存されているので簡単に取得できます。
final storage = FlutterSecureStorage();
String data = await storage.read(key: "{Keyname}") ?? "";
Cookieをサイトに設定
Key:Valueで保存されているので簡単に取得できます。
CookieManager cookieManager = CookieManager.instance();
final expiresDate = DateTime
.now()
.add(Duration(days: 7)) //有効期間
.millisecondsSinceEpoch;
await cookieManager.setCookie(
url: WebUri("https://example.com"),
name: "{Cookiename}",
value: "{Cookievalue}",
expiresDate: expiresDate,
isSecure: true,
);
実行のタイミング
これが迷ったポイントです。Cookieの永続化において必要なプロセスとパフォーマンスの低下を考慮した結果、以下のような処理とタイミングで行うことにしました。
- Cookieを取得(各ページロード時)
- Cookieをストレージへ保存(各ページロード時)
- Cookieをストレージから取得(アプリ開始時)
- Cookieをサイト用に設定(アプリ開始時)
上2つについてはアプリ終了時に動作させられるのが理想なのですが、ライフサイクルの監視などを試してみたところ特にiOSにおいてバッググラウンドの処理などの関係で確実に動作させることが難しいと判断しました。
以上、Flutterにおけるwebviewについでした!Flutterは初めて触ったので今後も活用できればと!
Discussion