フューチャー技術ブログ

Flutter でプッシュ通知するときに知っておきたいこと

はじめに

こんにちは。TIGの越島です。
Dart/Flutter連載 の5日目のお題はFlutterでプッシュ通知です。

Flutter製のスマホアプリにプッシュ通知機能をつけるとなったときに「最初に教えてもらってたら楽だったな〜」という情報をまとめてみました。また、最後に具体例としてFlutter x Firebase Cloud Messaging x Amazon Pinpointを組み合わせた場合の実現方法も簡単にご紹介します。

プッシュ通知の基礎知識

まずはプッシュ通知について、基本からおさらいをしていきましょう。

ローカル通知とリモート通知

プッシュ通知には大きく分けて以下の2種類があります。

  1. ローカル通知
  2. リモート通知

ローカル通知は、デバイスの内部で完結するプッシュ通知で、インターネット接続を必要としないものになります。リマインダーアプリで決まった日時に通知を飛ばす等、外部のサーバ(アプリのバックエンド等)からの通知リクエストを送る必要がない通知に利用されます。

リモート通知は、インターネットを通してスマホの端末外から届けられるプッシュ通知で、バックエンド側の何かしらのイベントの発生を受けてデバイスに送信されるプッシュ通知はリモート通知となります。LINEでメッセージを受信したときの通知や、SNSのいいね! の通知などはこちらにあたります。
ローカル、リモートそれぞれのプッシュアーキテクチャの構成

プッシュ通知配信サービス

リモート通知をAndroid/iOSのデバイスに対して送るためには、プッシュ通知配信サービスを利用します。

プッシュ通知配信サービスの代表的なものは、Googleが提供する Firebase Cloud Messaging (FCM) と、Appleが提供する Apple Push Notification Service (APNs) です。中国ではグレートファイアウォール等の事情でGoogleのサービスが使えないので、Baidu等が提供する同様のプッシュ通知配信サービスを使う必要があるようですが、そういった事情が無い限り、スマホへのリモート通知はFCMAPNsのどちらかで実現することになるでしょう。

FCMはAndroidとiOSのどちらにも通知を送信できますが、APNsはiOSへの通知送信のみをサポートする仕様となっています。よって、FlutterでAndroid/iOSの両対応を行う場合、FCMを利用すればプッシュ通知配信サービスも1つに集約できることになります。

プッシュ通知運用支援サービス

プッシュ通知の運用方法として、FCMやAPNsと直接やりとりしてプッシュ通知を送る方法がひとつの方法です。それ以外の方法として、プッシュ通知の管理・配信に役立つ機能を提供するプッシュ通知運用支援サービスを利用する方法もあります。

こういったサービスは、アプリ運用者とプッシュ通知配信サービスの間に立って、ABテストや配信結果の分析、ユーザーの行動に基づいた配信など、自前で整えようと思うと色々とコストがかかる便利機能を提供するサービスです。Amazon Pinpointは、こういったサービスの1つです。

プッシュ通知を配信するために必要な基盤を提供するFCM等のサービスと、プッシュ通知の運用支援を行うPinpoint等のサービスが、ネット上だとどちらも「プッシュ通知サービス」と表現されていることが多く、混乱しやすいので注意しましょう。この記事では区別のために、前者をプッシュ通知配信サービス、後者をプッシュ通知運用支援サービスと呼びます。

リモート通知が届くまでの流れ

次にリモート通知がデバイスに届くまでの一連の流れもおさらいしておきます。ここでは、プッシュ通知運用支援サービスを挟まず、プッシュ通知配信サービス(FCM)と直接やりとりをする構成で説明をします。

デバイストークンの発行と保持

まず、通知を送る前の準備として必要なのが、デバイストークンの発行と保持です。

デバイストークンはプッシュ通知配信サービスが通知を送るデバイスを特定するために利用する端末の識別子です。デバイストークンはプッシュ通知を送るときに絶対に必要になるもので、プッシュ通知配信サービス側で発行されます。デバイストークンの発行と保持の一般的な流れは下図のようになります。
デバイストークンの発行と保持

実際のアプリでプッシュ通知を出す場合は、LINEのメッセージ受信のように、アプリの特定のユーザに対してプッシュ通知を送りたいという場合が多いと思います。しかし、プッシュ通知配信サービスが管理してくれるのはデバイストークン(とそれが表す端末)のみです。そのため、アプリ上のユーザと、そのユーザのデバイスに対して払い出されたデバイストークンの対応関係は何らかの形で管理する必要があります。 Amazon Pinpoint等のプッシュ通知運用支援サービスには、ここの対応関係の保持をしてくれるものも多く存在します。

プッシュ通知の送信

デバイストークンの発行と保持ができたら、リモート通知を送る準備はOKです。

あとは、アプリのバックエンドで発生したイベントに応じて、通知を送りたいユーザのデバイストークン情報をプッシュ通知サービスに与えて、プッシュ通知を要求すれば、リモート通知がデバイスに送られます。
プッシュ通知の送信

Flutter x FCM x Amazon Pinpoint でプッシュ通知

最後に、具体例としてプッシュ通知配信サービスに Firebase Cloud Messaging(FCM)、プッシュ通知運用支援サービスに Amazon Pinpoint を使ってFlutterアプリにプッシュ通知送信をする仕組みを作る場合の構成や、大まかな実装の流れを説明します。

構成

全体の構成は以下のようになります。

Flutter x FCM x Amazon Pinpointのシステム構成

アプリバックエンドとプッシュ通知配信サービス(FCM)の間にAmazon Pinpointが入っています。デバイストークンとユーザIDの対応関係の保持はAmazon Pinpointで行います。特定ユーザに対するプッシュ通知の送信は以下のような流れとなります。

  1. アプリバックエンド→Pinpoint: ユーザIDを指定してプッシュ通知送信要求
  2. Pinpoint→FCM: 指定されたユーザIDに紐づくデバイストークンへのプッシュ通知要求を行う

実装の流れ

設定・実装の流れは以下のようになります。設定の細かいやり方は1、2年で割と変わってしまうので、この記事では示しません。できるだけ公式ドキュメントを確認しながら進めていくことを推奨します(参考になりそうなドキュメントを一部貼っておきます)

  1. FlutterとFirebaseプロジェクトを新規作成して接続設定をする(参考1参考2)。
    ※iOSとAndroidでそれぞれ設定が必要です
  2. Firebase→Flutterで通知送信できるように実装(参考サンプル実装
  3. Pinpointプロジェクトの作成・プッシュ通知設定をしてFCMと接続(参考1参考2参考3
  4. Pinpointとアプリバックエンドでやりとりする以下の処理を実装
    1. エンドポイント(デバイストークン)登録(参考
    2. ユーザID指定でプッシュ通知を送信(参考

Flutterは同じソースでAndroidとiOSを一気に対応できるところが魅力ですが、プッシュ通知はそれぞれのOS固有の仕様が深く関わってくる部分となるため、各OSに対して別々の対応が必要となる部分が出てきます。よって、それぞれの設定や実装が、(1)全体用(両方のOS用)のものか (2)Android用のものか (3)iOS用のものか、を整理して進めていくと混乱が起きづらいです。

例えば、Firebaseのプロジェクト上ではAndroidアプリとiOSアプリを別々で登録し、それぞれについてFlutterアプリ側から接続する設定を行う必要があります。Firebaseから見ると、iOSとAndroidで別々でアプリがあり、それぞれに対してプッシュ通知を送るような形になっているということです。