Sending Notifications to Flutter App

In this semester, our team tried to develop an mobile APP using Flutter. One user story is that when user are not using the APP, he/she should be notified when new friend request or new message coming

Since we are using firebase as our backend service, cloud functions can be used to monitor the database, and send notifications when triggered

This document provides a simple example:

img
  1. The function triggers on writes to the Realtime Database path where followers are stored.
  2. The function composes a message to send via FCM.
  3. FCM sends the notification message to the user's device.

Cloud Functions

Setting Triggers

Interactions between users is stored at /users/{userId}/interactions/{interactionID}in Cloud Firestore. Firebase SDK provide 4 triggers onCreate,onUpdate,onDelete,onWrite

In our case, we want to send a notification when user generate an interaction. So the function running on Node.js 8 should specify the document path and event type:

1
2
3
4
5
const functions = require('firebase-functions');

exports.notificationFCM = functions.firestore
.document('/users/{userId}/interactions/{interactionID}')
.onCreate(async (snapshot, context) => { /* ... */ });

Parse Data

Based on the data we need, we can set the FCM messages Notification messages will be displayed to end-user devices, data messages can be handled by client app and token is device registration token generated by FCM SDK in client app

For given platform, token can be got as follows

Users can have multiple devices, however, for convenience, just assume that token is stored as a string under the user profile

The content of interaction is a JSON like data passed by snapshot

1
2
3
4
5
6
7
8
9
10
{ metaData: {},
readed: false,
time: 1588268043715,
title: 'Friend Request from Leaf',
type: 'request',
userMeta:
{ displayName: 'Leaf',
photoURL: '',
uid: '' }
}

Once getting token and notification data, we can set the message

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const functions = require('firebase-functions');

exports.notificationFCM = functions.firestore
.document('/users/{userId}/interactions/{interactionID}')
.onCreate(async (snapshot, context) => {
const interaction = snapshot.data();
admin.firestore().collection('users').doc(context.params.userId).get().then((doc) => {
const deviceToken = doc.get('deviceToken');
var payload = {
notification: {
title: interaction.title,
},
data: {
click_action: 'FLUTTER_NOTIFICATION_CLICK'
},
token: deviceToken
};
});
});

Sending Message via Firebase Cloud Messaging

This is very straight forward, sending the message to target device, then receiving response or error code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const functions = require('firebase-functions');

exports.notificationFCM = functions.firestore
.document('/users/{userId}/interactions/{interactionID}')
.onCreate(async (snapshot, context) => {
console.log(snapshot.data());
const interaction = snapshot.data();
admin.firestore().collection('users').doc(context.params.userId).get().then((doc) => {
const deviceToken = doc.get('deviceToken');
console.log(deviceToken)
var payload = {
notification: {
title: interaction.title,
},
data: {
click_action: 'FLUTTER_NOTIFICATION_CLICK'
},
token: deviceToken
};
// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().send(payload)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
});
});

The cloud work is completed, next step is to make your device receive notifications

Firebase Messaging

Firebase Messaging is a flutter plugin for FCM, to use this, just update a dependency in the pubspec.yamlfile

The README file introduced how to integrate Firebase with your Android and IOS project, as we are using Cloud Storage and Firebase Auth. these part is already done yet. Then import the plugin and instantiate it in the Dart code

1
2
import 'package:firebase_messaging/firebase_messaging.dart';
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

BTW, The device token can be accessed by doing so

1
2
3
_firebaseMessaging.getToken().then((token) {
print(token);
});