こんにちは、この記事はflutter advent calendar 2018 9日目の記事です。
TL;DR
- 全然ネイティブアプリ作ったこと無いわしが、flutterでサクッと通知を受け取れるアプリを作った
- クオリティや保守性はさておき通知の実装できたので実装のポイントなど
- flutter いいよおいいよお
なぜつくることになったか
現在、私はcall.jpというサービスの立ち上げ、運営を手伝っています。 call.jpはWebページから、チューターや店員さんを呼べる呼び出しサービスです。
現在、ジーズアカデミーTOKYOなどで試験運用中です。
以下の通り、通知受取がPCにしかありませんでした。
なので、サクッと通知を受け取れるアプリを作ることになりました。
アプリの要件
要件は以下の通りです。
上記の要件を検討するにあたって、React Nativeなど検討しましたが以下からflutterがいいのでは、という話になりました。
- flutterがGoogle製なので、同じくGoogleで現在利用しているfirebaseと相性がよい
- 通知機能も問題なく両プラットフォームで実装できる
- Dartもそんなにとっつきにくくなさそう(JavaとかJavascriptとかSwitftやってればできそう)
- なんか最近、Twitter界隈でもよく見かけてイケてる感じがするw
なので、とりあえずflutterで簡単な通知アプリを実装してみることにしました。
つくったもの
名前の通り「通知を受け取るだけのアプリ」です。 ↓が実際につくったものです。
Firebase Cloud Messagingで通知を受け取る際のポイント
Firebase Cloud Messaingでflutterで通知を受け取る際のポイントは以下です。(すげぇ簡単です。)
- FirebaseMessagingのライブラリのインポート&アプリでFirebaseの設定
- アプリのログイン時、起動時など任意のタイミングで通知許可の設定を行う(iOSのみ)
- 通知受信時の挙動を定義する。
- トピックのサブスクライブを行う。
FirebaseMessagingのライブラリのインポート&アプリでFirebaseの設定
なにわともはれ、Firebase Messagingのライブラリのインポート&アプリでFirebaseの設定を行います。 Firebaseの設定は、Firebase公式のとこから各OSに合わせて、それに従います。 flutterの場合、プラットフォームに合わせて、各フォルダ下(ios, android)でfirebaseの設定を行います。
ライブラリのインポートはpubspec.yaml
に以下を追記します。
// pubspec.yaml dependencies: firebase_messaging: ^2.0.0 // ver番号は現在の状況に合わせて変えてください
アプリのログイン時、起動時など任意のタイミングで通知許可の設定を行う
ここからdartファイルに手を入れていきます。
自分が通知設定を行いたい画面のStateのinitState()
に通知許可の設定を入れます。
自分は、立ち上げ時に通知許可の設定を出したかったので、HomeScreen
に入れてます。
// home_screen.dart import 'package:flutter/material.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; // HomeScreenの宣言 class HomeScreen extends StatefulWidget { @override State createState() => new HomeScreenState(); } // HomeScreenのStateの宣言 class HomeScreenState extends State<HomeScreen> { final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging(); @override void initState(){ super.initState(); // ここで通知許可の設定を行う _firebaseMessaging.requestNotificationPermissions( const IosNotificationSettings(sound: true, badge: true, alert: true)); _firebaseMessaging.onIosSettingsRegistered .listen((IosNotificationSettings settings) { print("Settings registered: $settings"); }); }
通知受信時の挙動を定義する
同様にinitState()
の中で、通知受信時の挙動を定義します。
私の場合は、ダイアログが出ればよいので、buildDialog()
という関数を定義して
ダイアログを出すようにしています。
// home_screen.dart // ダイアログを出す関数の設定 void _buildDialog(BuildContext context, String message) { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return new AlertDialog( content: new Text("$message"), actions: <Widget>[ new FlatButton( child: const Text('CLOSE'), onPressed: () { Navigator.pop(context, false); }, ), ], ); } ); @override void initState(){ super.initState(); // ここで通知許可の設定を行う _firebaseMessaging.requestNotificationPermissions( const IosNotificationSettings(sound: true, badge: true, alert: true)); _firebaseMessaging.onIosSettingsRegistered .listen((IosNotificationSettings settings) { print("Settings registered: $settings"); }); // ここで通知受信時の挙動を設定しています。 _firebaseMessaging.configure( onMessage: (Map<String, dynamic> message) async { print("onMessage: $message"); _buildDialog(context, "onMessage"); }, onLaunch: (Map<String, dynamic> message) async { print("onLaunch: $message"); _buildDialog(context, "onLaunch"); }, onResume: (Map<String, dynamic> message) async { print("onResume: $message"); _buildDialog(context, "onResume"); }, ); }
ちなみに、onMessage
, onLaunch
, onResume
ってなんぞやと思っていると思いますので調べてみました。
flutterのfirebase_messagingライブラリのREADMEにばっちし載っています。
以下私の日本語訳
アプリ - フォアグラウンド | アプリ - バックグラウンド | アプリ - 停止中 | |
---|---|---|---|
Notification on Android | onMessage |
システムトレイに通知が格納される、もし通知をおしてアプリを開くとonResume が呼ばれる(click_action: FLUTTER_NOTIFICATION_CLICK の設定が必要) |
システムトレイに通知が格納される、もし通知をおしてアプリを開くとonLaunch が呼ばれる(click_action: FLUTTER_NOTIFICATION_CLICK の設定が必要) |
Notification on iOS | onMessage |
システムトレイに通知が格納される、もし通知をおしてアプリを開くとonResume が呼ばれる |
システムトレイに通知が格納される、もし通知をおしてアプリを開くとonLaunch が呼ばれる |
Data Message on Android | onMessage |
バックグラウンドにいる間はonMessage が呼ばれる |
本プラグインではサポートされていない。メッセージはロストする。 |
Data Message on iOS | onMessage |
メッセージはFCMによって保存されフォアグラウンドに戻ったときにonMessage が呼ばれる |
メッセージはFCMによって保存されフォアグラウンドに戻ったときにonMessage が呼ばれる |
まさかのDataMessage on Androidでアプリが停止中だとメッセージがロストする、という。。。(自分も今、初めて気づいた...)
トピックをサブスクライブ
最後にトピックをサブスクライブします。 今回は、ボタンを押してサブスクライブしています。
void _onChanged1() { _firebaseMessaging.subscribeToTopic("/topics/gsacademy"); _buildDialog(context, '通知の受信を開始します'); }
ちなみに、トピック以外にも端末者IDや通知トークンでも通知は受信可能です。
さいごに
flutterで動かしてますが、今の所、機能がシンプルなゆえ、基本問題なく、動いています。いやあflutter便利。
Firebase Cloud Messaging周りについては、以下のfirebase user group user meetupの資料にて詳しく扱っていますのでよろしければ参考にしてみてください。