iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
2
Mobile Development

Flutter---Google推出的跨平台框架,Android、iOS一起搞定系列 第 28

【Flutter基礎概念與實作】 Day28–使用FCM發送通知給使用者

今天是實作FlutTube的最後一天,程式碼也很少,大概30行左右,但這功能我覺得很酷,那就是Cloud Messaging,實作後你可以傳訊息到任何一台裝有FlutTube App的手機上,甚至可以依照不同使用者的類別傳遞不同的內容。

如果你對這個功能也有興趣,那就看下去吧。

Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost.
Yes

在Flutter要設定FCM非常的簡單,老樣子先引入package。

Messaging

在firebase資料夾下新增「messaging.dart」。
程式碼如下:

import 'package:firebase_messaging/firebase_messaging.dart';

FirebaseMessaging configureMessaging() {
  FirebaseMessaging firebaseMessaging = FirebaseMessaging();

  // only fire on iOS
  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('on Message: ${message}');
  }, onLaunch: (Map<String, dynamic> message) async {
    print('on Launch:');
  }, onResume: (Map<String, dynamic> message) async {
    print('on Resume:');
  });
  return firebaseMessaging;
}

前半部有兩行是iOS手機才會觸發到的,若沒加iOS手機就無法接收到訊息。
後半部在設定app在3種情況下(Message、Launch、Resume)收到訊息時,分別要做出什麼回應。

  • onMessage:當App正在執行中且手機畫面就是目前的App時觸發
  • onLaunch:當App完全被關閉(也不在背景執行)時觸發
  • onResume:當App正在背景執行時觸發

main

開啟main.dart,增加兩行程式碼,呼叫剛剛寫好的configureMessaging函式,並接收回傳的FirebaseMessaging物件實體。

final UserRepository _userRepository = UserRepository();
AuthenticationBloc _authenticationBloc;
FirebaseMessaging _firebaseMessaging;
@override
void initState() {
  _authenticationBloc = AuthenticationBloc(userRepository: _userRepository);
    _firebaseMessaging = configureMessaging();
    super.initState();
}

Android Mainfest.xml

如果想要在收到通知後讓正在背景執行的App執行某些行為(例如跳轉到特定頁面),為了能夠正確的收到Intent,這裡要設定intent-filter

開啟「android/app/src/main/AndroidManifest.xml」
貼上以下程式碼。

<intent-filter>
            <action android:name="FLUTTER_NOTIFICATION_CLICK" />
            <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

之後只要在自訂資料中加上
key: click_action, value: FLUTTER_NOTIFICATION_CLICK以及你想要跳轉的頁面,就可以執行相關的程式碼了。

相關資訊可以參考StackOverflow的回答。

iOS

由於我沒有mac可以測試,iOS的設定請參考官方教學

測試

以上設定弄好後,就可以到Firebase上傳送訊息測試看看。

可以設定訊息的標題和內容,另外也可顯示圖片,可以直接在右邊看到使用者接收到的效果是如何。

第二步驟你可以依照需求篩選會收到訊息的使用者族群。

第三第四步驟就跳過了。
第五步驟你可以輸入需要的參數值,採用key-value的方式存取。

確定沒問題後,就可以按下「審查」->「發布」,手機就會收到訊息囉。

記錄使用者FCM Token

我們還可以記錄使用者的Token,之後如果想要傳送訊息給單一使用者(例如通知他交易成功、帳號有問題等等),就能夠透過指定token的方式傳送訊息給他。

為了方便就直接把FCM Token紀錄在Firestore的User文件下吧。

Firestore Database

開啟firebase資料夾下的「firestore_database.dart」。
新增以下程式碼:

void updateProfilePictureUrl(String email, String url) async {
  print(url);
  await Firestore.instance.collection("Users").document(email).setData({
    'profile_picture_url': url,
  }, merge: true);
}

void updateUserToken(String email, String token) async {
  await Firestore.instance.collection("Users").document(email).setData({
    'fcm_token': token,
  }, merge: true);
}

updateProfilePictureUrl的setData,設定merge參數為true,如此一來如果資料庫中已經有同個email的文件的話,就會採用更新資料的方式,而不會把原本的蓋掉。
如果原本資料庫沒有找到這個email的文件就會新增一筆。

updateUserToken和上面一樣,只是是用來把token存到以使用者信箱作為識別值的文件中。

main

最後回到main.dart,由於上傳到資料庫需要email做為識別值,而email只有在Authenticated的State才能取得,所以要在狀態轉變成Authenticated時,先把取得的email和token上傳到資料庫,之後才跳轉到HomePage

if (state is Authenticated) {
        _firebaseMessaging
            .getToken()
            .then((token) => updateUserToken(state.userName, token));
    	return HomePage(
            email: state.userName,
        );
}

今日總結

Firebase Cloud Messaging是我覺得很酷又很實用的功能,有了FCM你可以依照使用者族群推播他會感興趣的內容或是幫自己廣告。增加使用者對App的黏著度。

FlutTube的實作到此告一個段落,App的功能以20天實作來說應該是滿完整的了,從基本的widget使用、Bloc Design pattern、串接API以及Firebase功能都有接觸到,希望對於剛接觸Flutter的人這次的專案實作是有幫助的。

完整程式碼在這裡-> FlutTube Github


上一篇
【Flutter基礎概念與實作】 Day27–在留言取得並顯示使用者的照片
下一篇
【Flutter基礎概念與實作】 Day29–Profile Mode檢測App效能
系列文
Flutter---Google推出的跨平台框架,Android、iOS一起搞定30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言