Flutter×Firebase(In-App Messaging)で、アプリ内通知をしてみる

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認ください</b></font>
* 25万文字を超える超大作になっています!!

---

## まとめ記事
* [Flutter系の記事のまとめ](https://qiita.com/kazutxt/items/524acb1c134015682ccf)

# はじめに
* 前回のFCMを用いた通知もいい感じでしたが、同じように使えるアプリ内通知もせっかくなのでまとめてみました。

# 概要
Firebase In-App Messaging(以下FIAM)は、アプリ内通知を行うための環境を提供します。

## 注意1
In-App Messagingは2021/5時点でベータ版の扱いですので、利用時はご注意ください

## 注意2
本チャプターはAndroidのみで動作検証を行っています


# 準備

まず、必要なライブラリをインストールします。

```yaml:pubspec.yaml
  firebase_core: ^1.1.0
  firebase_in_app_messaging: ^0.5.0+2
  firebase_analytics: ^8.0.3
  firebase_messaging: ^9.1.3
```

firebaseの基本となる`firebase_core`と今回使うFIAMのパッケージである`firebase_in_app_messaging`を入れます。
また、依存パッケージとなっている`firebase_analytics`もインストールします。

`firebase_messaging`は、インストールIDをを確認するために入れています。

# 実装

基本的に、firebaseと連携さえさせておけば、特段設定をする必要はありません。
ただし、In-App Messagingは、厳密な時刻指定ができず、数日に1回などのフェッチサイクルのため、テストをするために、手動でイベントを確認しに行くメソッドを呼び出しています。

`initState`の中で呼び出されている`fiam.triggerEvent('update_event')`が`update_event`というキャンペーン名を確認するロジックをいれています。

また、`FirebaseMessaging.instance.getToken()`は端末のインストールIDを確認するために、利用しています。

ソースコードの全体像は下記のようになります。

```dart:main.dart
import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static FirebaseInAppMessaging fiam = FirebaseInAppMessaging();

  @override
  void initState() {
    super.initState();
    fiam.triggerEvent('update_event');
    FirebaseMessaging.instance.getToken().then((String token) {
      print("$token");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
            child: Text(
          'FIAMテスト',
          style: const TextStyle(color: Colors.white),
        )));
  }
}
```

# 動作イメージ

Firebaseの左側のメニューから「In-App Messaging」を選択します。

![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/ff4bfe5e-11c7-e63a-b7cf-5a73ecf1d5c6.png)


デフォルトはカードなのですが、画像が必須のためモーダルを選択し、タイトルと本文を入れます。
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/29c8795f-74ae-2d8b-bf3a-f0a0fce21bb3.png)


次へを選択し、キャンペーン名と対象を入れます。
対象はAndroidアプリ全体としています。
![pic3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/3b209fd2-efc7-4dc6-5b48-0ec055473cef.png)


次へを選択し、公開をします。
![pic4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/75b2128d-27c4-fc36-7b5c-81ff4a0f7f2a.png)


端末でアプリを起動すると、通知が来ています。
![pic5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/da509456-aee5-ca28-44a5-f96376117857.png)


# CloudMessagingとの比較
CloudMessagingと異なり、バックグラウンドでの動作はできません。アプリが起動している時だけの表示となります。
また、フォアグラウンド中の実装はFIAMのほうが簡素ですが、細かい調整や時間の指定はできません。

# インストールIDを指定してテスト

## インストールIDの確認方法
`FirebaseMessaging.instance.getToken()`によって、IDを取得できます。インストールIDは、「NNNNN:MMMMM」となっているNNNNN部分となります。


```sh:result.sh
# tokenイメージ
c*****21SA*****gE*****:A*****FT*****8lLU_Y9nt*****e-4*****IvF8-5y*****6M*****6ye*****N*****4W-m*****02e*****u_*****7X4Q*****u-c*****fm*****YK2*****DL*****0e*****6U

# インストールID
# 「c*****21SA*****gE*****」の部分がインストールID
```

## 配信方法

下図の通り、デバイスでテストを選択し、インスタンスIDを入力してテストをクリックして
実施します。
![pic6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/e75f6c1f-5d8c-e8f0-1377-e7d11e57bc58.png)

# 連続実行時の注意

連続で実施すると、メッセージ自体は受信できていても、画面に表示されないような場合があるようです。

```sh:result.sh
I/FIAM.Headless( 4842): Successfully fetched 2 messages from backend
I/FIAM.Headless( 4842): Already impressed campaign update_event ? : false
I/FIAM.Headless( 4842): App foreground rate limited ? : true
I/FIAM.Headless( 4842): Already impressed campaign update_event ? : false
I/FIAM.Headless( 4842): App foreground rate limited ? : true
```