📟

LINE LIFF × Flutter Web:サンプルアプリで動作確認 〜js〜

2022/10/11に公開約4,800字

はじめに

LINE LIFF × Flutter Web でサンプルアプリを作ってユーザ情報を取得してみた。

したこと

  • LINE Developersの登録➜チャネル作成してLIFF IDの生成 [1]
  • web/index.htmlにLIFF SDKの記載
  • flutter_dotenvライブラリを用いてLIFF IDを本番環境で使用 [2]
  • jsパッケージを使用して、初期化処理とユーザー情報の取得

詳細

使用するフォルダ構成
project(root)
├─ lib
│  ├─ main.dart
│  └─ liff
│      ├─ liff_func.js
│      └─ liff_func_call.dart
└─ web
    └─ index.html
index.html
<head>
  <script src="flutter.js" defer></script>
  <!-- <head>配下に以下挿入 -->
  <script charset="utf-8"  src="https://static.line-scdn.net/liff/edge/versions/2.20.3/sdk.js"></script>
  <script src="../lib/liff/liff_func.js" defer></script>
  <!-- 以上 -->
</head>
liff_func.js
// 引数のLiffIdを基に初期化処理
async function liffInit(liffId){
    await liff.init({
        liffId: liffId,
        // 以下のプロパティをtrueで自動ログイン処理が有効に
        withLoginOnExternalBrowser: true,
    })
}

// profile情報を取得し、必要な情報をListにして返却
async function liffGetProfile(){
    const profile = await liff.getProfile()
    const profileList = [profile["userId"], profile["displayName"], profile["pictureUrl"]]
    return profileList
}
liff_func_call.dart
()
library liff_func;
import 'package:js/js.dart';

// jsファイルから関数呼出し
('liffInit')
external Object liffInit(String liffId);

('liffGetProfile')
external Object liffGetProfile();
main.dart
import 'dart:js_util';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:line_liff_sample/liff/liff_func_call.dart';

const List profileKeysList = ["userId", "displayName", "pictureUrl"];
Map profileMap = {"userId": "", "displayName": "", "pictureUrl": ""};
List? profile;

Future<void> main() async {
  // LiffIDを定義したenvファイル読み込み
  await dotenv.load(fileName: "env");
  String liffID = dotenv.get("LIFFID_KEY", fallback: "LIFFID not found");

  // Liff初期化処理
  await promiseToFuture(liffInit(liffID));

  // profile情報の取得
  profile = await promiseToFuture(liffGetProfile());

  // 取得したprofile情報をMapに格納
  for (int i = 0; i < profile!.length; i++) {
    profileMap.update(profileKeysList[i], (value) => profile![i]);
  }
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyAppBody(),
    );
  }
}

class MyAppBody extends StatelessWidget {
  const MyAppBody({Key? key}) : super(key: key);
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('LINE LIFF sample app'),
      ),
      body: Center(
        child: (profile == null)
            ? const Text("profile is null")
            : Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("ユーザーID: ${profileMap["userId"]}"),
                  Text("ユーザー名: ${profileMap["displayName"]}"),
                  const Text("トプ画:↓"),
                  SizedBox(
                    width: 250.0,
                    height: 250.0,
                    child: Image.network(profileMap["pictureUrl"]),
                  )
                ],
              ),
      ),
    );
  }
}

おわりに

  • 「LINE LIFF × Flutter Web:サンプルアプリで動作確認 〜flutter_line_liff〜」の派生Verとして、ユーザ情報を表示するだけのシンプルなサンプルアプリ。
     

  • 普段jsを触ることが無いため、jsライブラリの挙動を確認するのにものすごく手こずった。。
    jsの基本知識がある人ならもっと楽に使いこなせるのかと。。
     
    基本的なjsライブラリの使い方は「FlutterWebでjavaScript関数を呼び出す」をご参考に。
     
    jsパッケージは少し癖がある印象(私がjsに慣れていないだけ)なので、純粋にLINE LIFFの挙動を確認してみたい。ってレベルならflutter_line_liffの方が開発体験は良いかと。
     

  • [つまづきメモ]

    • js〜dart間の引数や戻り値のやり取りは、基本的にはObject型となること注意。
      →js側かdart側で型変換等の処理必要か。特にMap型の受け渡しは。[3]
      →@anonymous:ファクトリーコンストラクタ作成時に必要。
    • js:非同期処理についての理解不足(Promise型について等)。
    • dart:組み込み識別子の理解不足。factoryとか。[4]
       

参考記事

参考記事

 

脚注
  1. LINE Developers登録方法については検索すると記事たくさん出てくるので割愛 ↩︎

  2. flutter_dotenvについての参考記事: FlutterWebデプロイ時に'.env'が読み込まれない ↩︎

  3. 「How to use JavaScript libraries in your Dart applications」 ↩︎

  4. Dart:組み込み識別子一覧 ↩︎

GitHubで編集を提案

Discussion

ログインするとコメントできます