To get started with FCM, build out the simplest use case: sending a
test notification message from the
Notifications composer
to a development device
when the app is in the background on the device.
This page lists all the steps to achieve this, from setup to verification
— it may cover steps you already completed if you
have
set up a Flutter app
for FCM.
Install the FCM plugin
Install and initialize the Firebase SDKs for Flutter
if you haven't already done so.
From the root of your Flutter project, run the following command to install
the plugin:
flutter pub add firebase_messaging
Once complete, rebuild your Flutter application:
flutter run
Access the registration token
To send a message to a specific device, you need to know that device's
registration token. Because you'll need to enter the token in a field in the
Notifications console to complete this tutorial, make sure to copy the token
or securely store it after you retrieve it.
To retrieve the current registration token for an app instance, call
getToken()
. If notification permission has not been granted, this method will
ask the user for notification permissions. Otherwise, it returns a token or
rejects the future due to an error.
final fcmToken = await FirebaseMessaging.instance.getToken();
Send a test notification message
Install and run the app on the target device. On Apple devices, you'll need
to accept the request for permission to receive remote notifications.
Make sure the app is in the background on the device.
In the Firebase console, open the
Messaging page
.
If this is your first message, select
Create your first
campaign
.
- Select
Firebase Notification messages
and select
Create
.
Otherwise, on the
Campaigns
tab, select
New campaign
and then
Notifications
.
Enter the message text. All other fields are optional.
Select
Send test message
from the right pane.
In the field labeled
Add an FCM registration token
, enter the registration
token you obtained in a previous section of this guide.
Select
Test
.
After you select
Test
, the targeted client device (with the app in
the background) should receive the notification.
For insight into message delivery to your app, see the
FCM reporting dashboard
,
which records the number of messages sent and opened on Apple and Android
devices, along with data for "impressions" (notifications seen by users) for
Android apps.
Handling interaction
When users tap a notification, the default behavior on both Android & iOS is to open the application. If the application is terminated,
it will be started, and if it is in the background, it will be brought to the foreground.
Depending on the content of a notification, you may want to handle the user's interaction when the application
opens. For example, if a new chat message is sent using a notification and the user selects it, you may want to
open the specific conversation when the application opens.
The
firebase-messaging
package provides two ways to handle this interaction:
getInitialMessage()
: If the application is opened from a terminated state, this method returns a
Future
containing a
RemoteMessage
. Once consumed, the
RemoteMessage
will be removed.
onMessageOpenedApp
: A
Stream
which posts a
RemoteMessage
when the application is opened from a
background state.
To ensure a smooth experience for your users, you should handle both scenarios. The code example
below outlines how this can be achieved:
class Application extends StatefulWidget {
@override
State<StatefulWidget> createState() => _Application();
}
class _Application extends State<Application> {
// In this example, suppose that all messages contain a data field with the key 'type'.
Future<void> setupInteractedMessage() async {
// Get any messages which caused the application to open from
// a terminated state.
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
// If the message also contains a data property with a "type" of "chat",
// navigate to a chat screen
if (initialMessage != null) {
_handleMessage(initialMessage);
}
// Also handle any interaction when the app is in the background via a
// Stream listener
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
if (message.data['type'] == 'chat') {
Navigator.pushNamed(context, '/chat',
arguments: ChatArguments(message),
);
}
}
@override
void initState() {
super.initState();
// Run code required to handle interacted messages in an async function
// as initState() must not be async
setupInteractedMessage();
}
@override
Widget build(BuildContext context) {
return Text("...");
}
}
How you handle interaction depends on your application setup. The example above
shows a basic example of using a
StatefulWidget
.
Next steps
Send messages to foregrounded apps
Once you have successfully sent notification messages while your app is in
the background, see
Receive Messages in a Flutter App
to get started sending to foregrounded apps.
Go beyond notification messages
To add other, more advanced behavior to your app, you'll need a
server implementation
.
Then, in your app client: