Chapter 08

【コード解説:Flutter】FlutterでJavaScriptのブリッジコードを書いてliffと連携する

tokku5552
tokku5552
2022.11.23に更新

Liffの立ち上げ in Javascript SDK

アプリをliffに繋ぎ込む際にはLIFF SDKを使うと思いますが、FlutterはDartで書かれている為、SDKを直接使う事が出来ません。

そこでFlutterからJavaScriptのメソッドを実行する事を可能にしてくれるパッケージを使い、LIFF SDKを呼び出していきます。

今回はまずLIFF SDKのinitメソッドをFlutter側から呼び出してみましょう。

使用パッケージ

こちらのjsパッケージを使っていきます。

https://pub.dev/packages/js

実装

大まかな手順は以下の通りです。

  1. jsパッケージをインストール
  2. LIFF SDKをインストール
  3. LIFF SDKを呼び出すjsの処理を定義
  4. 定義したjsの処理をDartで呼び出すインターフェースを定義
  5. 定義したDart側のインターフェースを呼び出す

ディレクトリ構成

.
├── pubspec.yaml # jsパッケージをインストール
├── ...
├── web
│  ├── index.html # LIFF SDKをインストール
│  ├── ...
│  └── flutter_liff.js # LIFFを呼び出すjsのメソッドを定義
│
└── lib
    ├── main.dart # インターフェースに定義されたメソッドを呼び出す
    ├── ...
    └── js
        └── flutter_liff.dart # jsメソッドを呼び出すインターフェース

1. jsパッケージをインストール

プロジェクトのルートで下記コマンドを実行し、jsパッケージをインストールします。

$ flutter pub add js

2. LIFF SDKをインポート

次にLIFF SDKを呼び出せる様にFlutter Web側でインストールします。

web/index.html
<script  charset="utf-8"  src="https://static.line-scdn.net/liff/edge/versions/2.20.3/sdk.js"></script>

https://github.com/tokku5552/flutter_liff_scheduler/blob/main/web/index.html#L41

3. LIFF SDKを呼び出すjsの処理を定義

liff idを引数で受け取り、initメソッドに渡すシンプルなメソッドを定義します。

web/flutter_liff.js
async function init(liffId){
    console.log("init called")
    await liff.init({
        liffId: liffId,
    })
}

4. js処理を呼び出すDartのインターフェースを定義

今度は上記のメソッドを呼び出すDartのインターフェースを定義します。

まず大前提としてはjsパッケージではjs側のファイルや処理を呼び出すコードの前に@JS()アノテーション付けます。

lib/js/flutter_liff.dart
() // jsライブラリ読み込みの為のアノテーション
library flutter_liff; 

import 'package:js/js.dart';

('init') // jsライブラリ内のメソッドの為のアノテーション
external Object init(String liffId);

jsの処理を定義したファイルをライブラリとしてインポート。読み込まれてるのは先ほど定義したflutter_liff.jsです。

()
library flutter_liff;

次にjsパッケージも忘れずにインポート。

import 'package:js/js.dart';

そして以下がメソッドのインターフェース定義になります。

('init') // 対応するjsの処理を定義
external Object init(String liffId);

メソッドのインターフェースではJSアノテーションでどのjsの処理に対応するかを定義しています。

dartメソッドの頭にexternal句を付けて引数、返り値をjsの処理と同様にします。

本来initメソッドには返り値はありませんが、flutter_liff.jsに定義したinitメソッドは非同期処理となる為、返り値はPromiseになります。

Dart側ではPromiseはそのままでは扱えない為、Object型として受け取っています。

5. 呼び出す

main関数内で定義したinitメソッドを呼び出します。

lib/main.dart
import 'js/flutter_liff.dart' as liff;
import 'package:js/js_util.dart'; 

Future<void> main() async {
    final liffId = // envファイルから取得
    await promiseToFuture(liff.init(liffId));
}

手順としては以下の通りです。

  1. initメソッドを定義したファイルをインポート
  2. envファイルなどからliffIdを取得
  3. liffIdを引数に定義したメソッドを実行

通常、Dartの非同期処理Futureawait句を付けるだけで良いのですが、js側から返されるPromiseは一度Futureに変換する必要があります。

その為、jsパッケージ内のjs_utilに定義されているpromiseToFutureメソッドでラップしてあげる事でjsから渡ってくるPromiseを変換してあげます。

以上を実装した後、コンソールにて"init called"のメッセージが表示されていれば、繋ぎ込み完了です。