Enabling Firebase Cloud Messaging Push Notifications with Flutter.

Overview

Peter Birdsall
Sep 4, 2018 · 17 min read

Using Firebase Cloud Messaging (FCM) Push Notifications in Flutter for iOS and Android is mostly a matter of setup which requires a bunch of specific steps that are different for both iOS and for Android. The nice thing about using FCM is that as long as your not sending an extensive amount of messages, more than 1000 at a clip and a typical delivery time of about 250ms with a payload of less than 4K and a persistence limit of 100 messages prior to messages collapsing, its free and it works. You can also add up to four key-value pairs and although I’m not a backend developer, there seem to be a good number of options for integrating it with your backend services in a number of languages, so you don’t have to use Dart if your unfamiliar with it.

There are two types of FCM push notifications; a Notification message and a Data message. For my implementation I’m using Notification messages since using Data messages can be more complex in terms of handling the notification and the application state. For the application there is only a concern with receiving push notification messages either when the app is in the foreground or receiving a notification in the platforms notification system, which if clicked would then open the application.

What you’ll need.

In order to use Firebase Cloud Messaging you’ll need a google gmail account for Firebase console. For iOS development it will require a Apple Developer account and also a reasonably recent Mac or a virtual machine in order to be able to run XCode, the IDE for iOS and it’s associated simulator and a physical iOS device. For Android Development an IDE like Intellij or Android Studio and it’s emulator. A note on Android Studio, only use a release version, the Canary channel versions don’t work with Flutter as of the writing of this article.

XCode considerations.

You’ll need XCode 9.2 or later, I used version 9.4.1. It also requires that your project targets iOS 8 or above. In addition to actually test push notifications on iOS you will need a physical phone.

As previously mentioned, each mobile platform requires different configuration steps. So for Android only developers, like me, let’s handle the tougher iOS configuration first. If you already have any of these pieces setup on your Apple Developer account, you can skip them. This article was written from the perspective of your setting this all up for the first time. I will go thru each step in detail under the assumption that it is unfamiliar to Android developers that haven’t worked in the iOS realm.

There are 5 major steps that we will go thru as follows:

  1. Add your physical iOS device on your Apple developer account.
  2. Create a Flutter app and a Firebase project.
  3. Add your iOS app to the Firebase project (This is pretty long).
  4. Add your Android app to the Firebase project
  5. Add Firebase Cloud Messaging callbacks in your Flutter code.

OK, Let’s get started.

1) Add your physical iOS device on your Apple developer account.

First you’ll need to find your unique id of your iOS device, known as your UDID. I used this link to find the UDID and since I’m not that familiar with iTunes, I used the without iTunes option on a Mac. I’m doing this step now, just to keep a later step simpler. Now add your device on your Apple Developer account. First click on Certificate, Identifiers & Profiles.

click on Certificate, Identifiers & Profiles.

Under Devices, select your type of device, i.e. iPhone or iPad then click the ‘+’ sign in the upper right.

select your type of device, i.e. iPhone or iPad then click the ‘+’ sign in the upper right.

Fill in the device name and put the UDID from the prior step and click the Continue button.

Fill in the Name: and UDID: and click Continue.

Now actually register the device by clicking Register.

Click the Register button.

You’ll then come to the completion screen, just click the Done button.

click the Done button.

2) Create a Flutter app and a Firebase Project.

Please note that this article has updates that refer to using firebase_messaging version 2.0.0.

You’ll have to add your iOS application to Firebase via the Firebase console, in order to do that you’ll first have to have created your Flutter application so that it generates the code for iOS and Android.

Add the Firebase Cloud Messaging dependency to your Flutter app.

In your pubspec.yaml file you’ll need to add the firebase_messaging dependency for Firebase Cloud Messaging as follows:

dependencies:
flutter:
sdk:
flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
firebase_messaging: ^2.0.0

Your version of firebase_messaging library may be different, you can check this at firebase_messaging library. Next you can either click on Packages get in Android Studio (or equivalent in another IDE) or a flutter packages get in the console.

Then you should create a Firebase project. To log into the Firebase console you will need to do it with a gmail account.

Click Add project

Enter the name of your new project and click Continue.

Click Continue.

Click Create Project.

Click Create project.

Click continue.

click Continue.

3) Add your iOS app to the Firebase project.

Click on iOS

Get your bundle. In iOS it maybe in CamelCase, so it’s best to get it from Xcode. You can open XCode from Android Studio with your Flutter project open, right click on the iOS folder in your project and there will be a ‘Flutter’ tab a little more than a third of the way down. Once you highlight the Flutter tab by placing your mouse over it, it will show you a submenu item ‘Open iOS module in XCode’. Click Open iOS module in XCode.

click Open iOS module in XCode.

Alternatively you can navigate to the folder your Flutter project is in with XCode and then simply open the iOS folder that contains your iOS generated code from the Flutter application your working on.

Also while you are there make sure Automatically manage signing is checked and that you have entered your team, otherwise you will not get the Push Notifications capability which is used later.

Copy your bundle identifier

Add the bundle identifier to Firebase project and click Register app.

Add the bundle identifier and click Register app.

Download the Google Services property list file.

IMPORTANT: Download the property list file into a separate folder as it can only be added by Xcode by a drag and drop. If you just download into you XCode project, that won’t work.

Save this file in a separate folder.

Get a copy of the GoogleService-Info.plist file and drop and drag it into Runner/Runner folder while in Xcode (Note: Make sure it’s not the root Runner folder)

copy of the GoogleService-Info.plist file and paste it into Runner/Runner

You will get a completion dialog window, just click Finish.

click the Finish button.

After you have copied the plist file then click on it and make sure that your target membership is checked on the right side of your screen.

if Runner isn’t check, please check it.

You can skip the next two steps. Skip the Add Firebase SDK by clicking next since we are just using push notifications.

click the Next button.

Now it’s time to run your app on either a iOS simulator or real iOS device to see that your iOS app is registered with Firebase. Go to Android Studio and if necessary open the iOS simulator or connect a real iOS device and after the simulator/iOS device is active, click the green run button.

After your app is running go back to the Firebase console and after a little bit of time you should see the ‘Congratulations, you’ve successfully added Firebase to you app!’ with the checked icon under step 5 Run you app to verify installation. You can then click the Continue to console button.

after you get the Congratulations message, click Continue to console button.

Now add your application as and App Id on your Apple Developer account. First click on Certificate, Identifiers & Profiles.

Click on Certificate, Identifiers & Profiles

Now add a key, Select All under Keys and the plus sign in the upper right.

click and the plus sign in the upper right.

Add your description and select Apple Push Notifications service (APNs) and then at the bottom of the screen select Continue.

enter your Key Description name and click Apple Push Notifications service (APNs), then scroll down.

Next click Confirm.

click the Confirm button.

Now copy the Key Id

copy the Key ID: string

Now go back to your Firebase project and go to project settings.

go to Project settings.

Then click on Cloud Messaging and go to your iOS app definition and click Upload.

click Upload.

Then past the Key Id

past the Key Id into Key ID field.

Go back to your Apple Developer page and click download on the Key file.

click the Download button.

Back on the Firebase console click browse and open the Key file you just downloaded.

Next you have to add your Apple Id prefix, which can be obtained from your Apple Developer account Membership Team ID.

copy the 10Digit number from Team ID.

Copy the Team ID into the App ID prefix on the Upload APNs auth key screen on the Firebase console then click the Upload button.

Paste the Team ID into the App ID prefix field and click Upload.

Create an App ID on the Apple Developer console.

This and the next steps where key to getting Firebase Cloud push notifications working. First on the Apple Developer console you need to create an App Id for your application. Back under Certificate, Identifiers & Profiles select the App IDs under the Identifiers tab and click the ‘+’ button in the upper right.

select the Identifiers tab and click the ‘+’ button in the upper right.

Enter your description of your application for the APN in the name field of App ID Description and your App ID Prefix from the Team ID from the Apple Developer Membership page, as described previously.

enter the App ID Description, check the Explicit App ID and scroll down.

Next select Explicit App ID and enter you Bundle ID from XCode. Then further down the page in Services select Push Notifications and hit the Continue button.

select Push Notifications and click the Continue button.

You will then get a registration confirmation page and Push Notifications should be marked as Configurable, then click the Register button.

click the Register button.

Creating a Provisioning Profile

You’ll need to create a provisioning profile to enable debug testing for your real physical iOS devices. You can either add to or create a new provisioning profile as needed. Back under Certificate, Identifiers & Profiles select the All tab under Provisioning Profiles and click the ‘+’ button in the upper right.

select the All tab under Provisioning Profiles and click the ‘+’ button in the upper right

Select iOS App Development and click Continue.

select iOS App Development and click Continue.

Select your App Id that you registered in the prior step and click the Continue button.

select your App ID and click the Continue button.

Select either the particular certificate that will be generated or select All. Note if there is only one certificate, the one your currently creating, then when you select it, then All will automatically be selected. Click the Continue button.

select your provisioning profile certificate and click the Continue button.

Select your device or devices and click the Continue button.

select your device or devices and click the Continue button.

Give your profile a name in the Profile Name field and click the Continue button.

enter your profile a name in the Profile Name field and click the Continue button.

Click the Download button.

click the Download button.

You should save the file by clicking the Save button and then click the Done button.

click the Save button.

Navigate to the file you just saved and double click on it to implement the provisioning file.

Enable the push notifications capabilities in XCode.

Now that you have created the App Id and implemented the provisioning file you should be read for the last step for iOS. Yes I said the last step! for iOS.

Go back to XCode and select the root Runner folder and select Capabilities. Then scroll to Push Notifications and make sure if set to ‘ON’. If not click the ON switch.

If you had to click the Push Notifications ON switch then click on the General tab then the Capabilities tab. This is a double check that XCode had enough time to set the Push Notifications on and that it is in fact ON.

enable Push Notifications.

The XCode info.plist file requires a further configuration, it requires a entry for FirebaseAppDelegateProxyEnabled to be set to NO. In the Runner/Runner folder double click on the info.plist file. Then in the center space below the info.plist file do a right click and an options menu will appear. Click the ‘Add Row’ option.

In the empty Key row entry put the value ‘FirebaseAppDelegateProxyEnabled’ and then in the value put the value ‘NO’

Whew! You gotten thru all the configurations steps for iOS. We’ll do the easier part now, adding the Android app to your Firebase project.

I ran across a post that mentioned that there can be an issue user_frameworks. Remove the use_frameworks! line from ios/Podfile (workaround for flutter/flutter#9694).

4) Add your Android app to the Firebase project.

Go to your Firebase project and go to project settings.

go to Project settings.

Click the Add app button.

click the Add app button.

Choose Add Firebase to your Android app.

click the green Add Firebase to your Android app button.

Add your package name to the Android package name field and click Register app button.

enter your package name and click the Register app button.

Add the Google Services file for Cloud Messaging to your Android application. You can download this config file directly into you Android app folder in your in your Flutter project. Click the Download google-services.json file.

click the Download google-services.json button and save it in the Android app folder.

Here’s where that file should be saved and how it should look after you’ve saved it there.

Next add the dependencies that you need to your gradle files.

add the class path and dependencies to the respective build.gradle files and then click the Next button.

Add the classpath to your project level build.gradle file.

classpath ‘com.google.gms:google-services:4.0.1’

You can skip adding the firebase-core dependency since we are only using Firebase Cloud Messaging and not any other specific Firebase capabilities.

Add the google services plugin to your application level build.gradle file.

apply plugin: ‘com.google.gms.google-services’

You can then sync your project and then click the Next button.

Now run your project on either a Android emulator or physical device, it will work on either. After your app is running go back to the Firebase console and after a little bit of time you should see the ‘Congratulations, you’ve successfully added Firebase to you app!’ with the checked icon under step 5 Run you app to verify installation. You can then click the Continue to console button.

run the Android app, receive the Congratulations message and click the Continue to console button.

In addition the Android Intent messaging system must be notified that a message notification has occurred from Firebase Cloud Messaging. This is accomplished by adding the intent filter to the manifest for your application. Under your ‘android’ folder in your Flutter project navigate to ‘app’ folder and expand it, then to the ‘main’ folder and expand that. Within the main folder there will be a AndroidManifest.xml file. Double click on that and add the following code below the last <intent-filter> xml tag.

<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Navigate to Android/apps/main and double click on the AndroidManifest.xml file and add the above code.

So what this does for you, is when you application is not active on Android, the Firebase Cloud Messaging has sent a notification to your application and you click that notification it will generate a FLUTTER_NOTIFICATION_CLICK intent message on your device. The Android intent message system will then search for an application that can handle this for the package and then find the intent filter you defined in the AndroidManifest and trigger the action in your application and bring it into an active state.

5) Add Firebase Cloud Messaging callbacks in your Flutter code.

Firebase Cloud Messaging listener callbacks in Flutter.

Flutter needs to be able to handle several callbacks from Firebase for a number of different states. When your app is not active and you get a notification from a FCM push message and then click on that notification your app should then be activated. When this occurs the onLaunch: callback will be the entry point into your application. When your app is in the background and you get a notification your app will be brought to the front and the onResume: will be the entry point into your application. Last and the easiest is when you get a notification and your app is active, then you just want to receive the message. For this the onMessage: will be the entry point into your application.

Setting up the code for Firebase Cloud Messaging.

Next is to add the ability to actually handle the callbacks, just discussed above, to the Stateful page widget that you want to receive your push notifications on. In my example the I’ll be using a widget called HomeScreen and it state class called HomeScreenState. All of the work happens in the state class.

You’ll need two imports in your Dart file if they aren’t already there; dart:io and package:firebase_messaging/firebase_messaging.dart. The firebase_messaging.dart import is obviously for Firebase Cloud Messaging. The dart:io import give you support for interrogating whether your application is running on Android or on iOS. This will be explained shortly for a step that is required on iOS devices.

import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';

Next create a variable for Firebase Cloud Messaging in your state class, right as after it’s declaration as follows:

FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

I’ve created a FCM listener method and a iOS permission dialog method, these should be called from your overridden initState method within your state class.

@override
void initState() {
super.initState();
firebaseCloudMessaging_Listeners();
}
void firebaseCloudMessaging_Listeners() {
if (Platform.isIOS) iOS_Permission();

_firebaseMessaging.getToken().then((token){
print(token);
});

_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print('on message $message');
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
}

void iOS_Permission() {
_firebaseMessaging.requestNotificationPermissions(
IosNotificationSettings(sound: true, badge: true, alert: true)
);
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings)
{
print("Settings registered: $settings");
});
}

At some point, and I haven’t identified exactly when, I can only attribute to at this point for version 2.0.0 of Firebase_Messaging package so far. The listeners for message will have to be changed to ‘async’ for onLaunch, onMessage and onResume in the Flutter code. The above code has been changed to reflect this. In addition, the Map of the ‘message’ has also changed.

If you are using Firebase Messaging package that is less than 2.0.0, then remove the ‘async’ for the onMessage, onResume and onLaunch in _firebaseMessaging.configure above. The code line would look as follows:

onMessage: (Map<String, dynamic> message) {
...
onResume: (Map<String, dynamic> message) {
...
onLaunch: (Map<String, dynamic> message) {

The firebaseCloudMessaging_Listeners() method checks whether you are running on an iOS device if (Platform.isIOS) and then call a dialog iOS_Permission() method to request the permission on iOS, which is required. This is how that dialog will look when the application runs on an iOS device.

iOS Push Notifications Permission dialog.

The next step is used to get a FCM token which will uniquely identify the device from a FCM perspective, in case you want to send a message directly to this device, this is the token you would use in FCM to send a message specifically to this device. The _firebaseMessaging.configure then handles the onLaunch, onResume and onMessage callbacks, we discussed. In my code I only do a print of information, you can replace this with whatever processing you desire.

Important Note: On iOS push notifications will only work on a real iOS device. Simulators do not currently support push notifications, so a real device must be used. I’ve seen some comments that you can get push notifications to work on a 6 or 6p device, but I wasn’t able to get that to work, probably because it requires an iOS project of 8 or higher.

In Summary.

This article was mean to bring you thru the configuration steps for configuring and core code for Flutter, it does not cover sending any actual test messages from either the Firebase console or from a server. This article was meant to show all the configuration steps, especially all the details for iOS configuration, that I researched, collected and found challenging. I didn’t want to overload you with information, as there were enough steps in this article. If you want further instructions on sending messages from the Firebase console,I’d be glad to add it, but there are plenty of resources on that.

Revised 9/14/2018 Variable added, moved a step, changed a Tag, added Intent-Filter.

Revised 9/15/2018 Updated code to run with the firebase_messaging 2.0.0 package.

Revised 9/16/2018 XCode required FirebaseAppDelegateProxyEnabled set to ‘No’ in info.plist.


The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.

FlutterPub

The Pub(lication) for all about the Flutter and its magic

Peter Birdsall

Written by

A passionate Android Developer, excitingly working with Flutter for a client.

FlutterPub

The Pub(lication) for all about the Flutter and its magic

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade