Firebase Cloud Messaging with Flutter

Tugba Çekirge
CodeBrew
Published in
7 min readJul 28, 2022

Hello,

My name is Tugba; I am acting as a software development team lead at Arkitek R&D. In Arkitek, we are building mobile, desktop, and web applications using technologies such as VueJS, Flutter, and C#. Since 2021, We have been developing our web/mobile projects in Flutter, and needless to say, Flutter is amazing. After two years, we hived many know-how and some workarounds and I will try to share whenever I find a chance.

If you like my content, you can buy me a pizza!

In this article, I will try to explain our step-by-step guide to

1- How to add FCM to your Flutter mobile application and manage subscriptions.

2- How to send messages to your application: Server-side

Before I begin, I would like to mention and thank my junior, Ekin Berk Bozkurt for the amazing work and the great effort that he puts in our flutter projects. We love you, Ekin ❤

And one more thing! This is my first medium post so excuse me if I make mistakes.

Ok, let’s begin.. :)

Our flutter project is running on multiple platforms: IOS, Android, and Web. In this article, I will just walk through FCM to IOS and Android platforms.

First, we are going to create and register our apps in FCM. I’m going to try my best to not leave holes in the process but if I do, please excuse me.

  1. Go to https://console.firebase.google.com/ and create your project if you haven't yet.

2. Select IOS App (If you are not building an IOS app, you can skip 2 and jump to 3)

There are 5 steps to follow for registering an IOS app:
2.1 — Register your app. FCM asks for some information (Apple ID etc) that you can easily get from AppStoreConnect
2.2 — After you complete the form, you will get a GoogleService-Info.plist file. Download the file -> Open XCode -> Go to Runner-> Add this file in the same folder where your Info.plist is. (Important: You need to perform this action with XCode, otherwise it doesn’t work. Do not use VS-Code or file explorer etc..)

2.3 — Adding Firebase SDK: ** this action occurred an error and took it back after **
Open XCode again, see the “Add Packages” section. Type https://github.com/firebase/firebase-ios-sdk and enter. It will show libraries you can add, I will only choose analytics and messaging.

2.4 — Open your AppDelegate.m file from XCode and make these imports
@import FirebaseCore;
@import FirebaseMessaging;
@import FirebaseAnalytics;

and these lines:
(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

if (@available(iOS 10.0, *)) {
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
}
— →>>> [FIRApp configure]; <<<<← — — — — -
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

2.5 — Go back to the firebase console, select your IOS project and click the “Settings” icon and go to the Project Settings page. Go to the “Console Messaging” tab. We need to register our APNs Authentication Key(Apple Push Notifications), which you can get by following the steps below:

go to -> https://developer.apple.com/account/resources/certificates/list
2.5.1 — Add New Key
2.5.2 — Name your key as you like, I used something like MyAppNameAPNs
2.5.3 — Click and check the Apple Push Notifications service
2.5.4 — continue -> register
2.5.5 — Download
2.5.6 — Copy Name and KeyID (you will need this information)

Return to firebase console. Click APNs Authentication Key, upload the file at step 5, and enter KeyID and your TeamID (apple developer account -> membership)

Now let's add FCM to our Android Project: ( If you are not developing an Android project, skip 3 and jump to the 5th step)

3 — Go to the firebase console, and add an android project.
3.1 — Enter your app information and continue.
3.2 — Download google-service.json
3.3 — Open VSCode and add this file under the app folder.
3.4 — Open app/build gradle and add implementation lines in dependencies and apply plugins

dependencies {
implementation platform(‘com.google.firebase:firebase-bom:30.1.0’)
// Add the dependency for the Firebase SDK for Google Analytics
// When using the BoM, don’t specify versions in Firebase dependencies
implementation ‘com.google.firebase:firebase-analytics’
}
apply plugin: ‘com.google.gms.google-services’
apply plugin: ‘com.android.application’

3.4 — Open build.gradle and

3.4.1 — Add this line in the dependencies section:

  • classpath ‘com.google.gms:google-services:4.3.10’ // Google Services plugin

3.4.2 — Add google() to repositories in all projects and build script.

Your build gradle should look like this:

build.gradle

4 — for IOS -> Open XCode -> targets -> select your project-> sign in & Capabilities
Click + (plus) button and select

  • push notifications -> check
  • background modes -> check these two:
    — background fetch
    — remote notifications

Follow this document if you need a more detailed explanation
https://firebase.flutter.dev/docs/overview
5 —Open VS Code and go to your terminal and enter these in order:

5.1 — flutter pub add firebase_core

5.2 — dart pub global activate flutterfire_cli

5.3 — export PATH=”$PATH”:”$HOME/.pub-cache/bin”

if you get this error -> Warning: Pub installs executables into $HOME/.pub-cache/bin, which is not on your path.
You can fix that by adding this to your shell’s config file (.bashrc, .bash_profile, etc.)

5.4 — firebase login

will ask for credentials, you need to enter the one you are using in the firebase console.

5.5 — flutterfire configure

Select your project.

It will create firebase_options.dart file.

6- We are managing our FCM functions in a single dart file so we can access it properly. Create a file and name FCMFunctions.dart

Our FCMFunctions.dart is something like this:

7 — Open main.dart

import ‘package:arkitek_app_internal/data/FCMFunctions.dart’;

and call your functions in runApp

main.dart

Note: At line 9, we are subscribing to a channel that we named “All”. We are using this to send notifications to everyone. Also after login, we are calling

await fcmFunctions.subscripeToTopics(“acc” + response[0][‘AccID’].toString());

So every user is subscribed to two channels by default: All and to its own account channel. We decided to follow this way because managing user-based notifications were very complicated and challenging.

// how to manage user base notifications in short -> you need to get an FCM token, store it in DB, and archive every token if it’s older than two months because there’s no method to check if the token is valid. So yeah, we didn’t want to go that way.

7 —Go to pubspec.yaml and add
firebase_messaging: ^11.4.2
firebase_analytics: ^9.1.9

note: I removed firebase SDK from dependencies because I got an error.

Don’t forget to save (pub get)

Freebie:

We were using image_picker in our project and got this error whilst we were implementing FCM. If you get this error, it means your gradle is outdated and you need to update:
Execution failed for task ‘:app:lintVitalRelease’.
> Could not resolve all artifacts for configuration
‘:image_picker_android:debugUnitTestRuntimeClasspath’.

how to fix:
1 -> pubspec.yaml -> image_picker: ^0.8.5+3
2 -> gradle-wrappler.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
3 -> build.gradle ->> dependencies
classpath ‘com.android.tools.build:gradle:7.1.2’

So, the client-side is pretty much like the above. Let’s dive into the server side and I will try to explain, how we send our notifications.

We are using C# in our backend projects. If you are familiar with it, this will be pretty easy to follow.

— — — — — — — — — — — — — — — —
SERVER-SIDE
— — — — — — — — — — — — — — — —
The document I followed: https://firebase.flutter.dev/docs/messaging/server-integration

1 — First, we need to install FirebaseAdmin so we go to NuGet and install the package

Install-Package FirebaseAdmin -Version 2.3.0
2 — After installing FA, open firebase console -> go to Project Settings -> Cloud Messaging -> Manage Service Accounts -> select account -> KEYS -> add key and
download the JSON file. ** we will use this file to get token from google **
3 — Add this file to your solution because we are going to read it for our credentials. (there are other options for credentials, you can look it up if you are curious) (Important: do not share that file publicly)

4 — We need a class for our notification. Our MessageMain class is something like this:

Notification.cs

5 — Sending notification!

5.1:

import these using:

using Google.Apis.Auth.OAuth2;

using Newtonsoft.Json;

Create a function

SendNotification(){

…….

MessageMain messageMain = new MessageMain();

Message message = new Message();

Notification notification = new Notification();

AndroidConfig android = new AndroidConfig();

android.Priority = Priority.High; // this is important. It allows your notification to pop even when the app is on and running (for Android)

message.Android = android;

notification.title = “New task: “ + dsWork.WO_WORKS[0].DESCRIPTION;

notification.body = dsWork.WO_WORKS[0].DESCRIPTIONDETAIL;

message.Notification = notification;

message.topic = “acc” + AA_ACCOUNTS[0].ID; // this is important. It’s the user’s subscribed channels for its own account.

messageMain.message = message;

var accessToken = await GetAccessToken().ConfigureAwait(false);

var url = “https://fcm.googleapis.com/v1/projects/{YOUR-PROJECT-NAME}/messages:send";

HttpClient client = new HttpClient();

client.BaseAddress = new Uri(url);

client.DefaultRequestHeaders.Accept.Clear();

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, accessToken);

string json = JsonConvert.SerializeObject(messageMain);

var content = new StringContent(json, Encoding.UTF8, “application/json”);

var result = await client.PostAsync(url, content);

FOR GetAccessToken ->>

GetAccessToken function

To SumUp → We created a method named, “SendNotification” in our case, it gets task details and user info. We initialize our MessageMain class and other child classes and set properties accordingly. After that, we called GetAccessToken and get our token from google to send our notification and post it via HttpClient.

And this is it! This is how we implemented FCM to our IOS and Android applications. I tried to be straightforward as much as I could and mentioned some important anecdotes to save time.

--

--

Tugba Çekirge
CodeBrew

Cat mom, metalhead, old gamer, software developer