Independent Notification service using Ionic, Node & FCM

Shubham Rath
hirewithparam
Published in
6 min readJul 4, 2018

--

We all have seen the push notifications that an app does in android or IOS. How can we implement that using Ionic? Moreover, how to regulate such a service? In this article we will create a completely independent notification service that will be able to send push notifications to both Android & iOS. We will be using Firebase Cloud Messaging service for the push notifications.

Step 1

Create a new ionic application. I am using the tabs template here.

ionic start node-ionic-notifications tabs
cd node-ionic-notifications

Step 2

Install the required dependencies for native support.

ionic cordova plugin add cordova-plugin-firebase
npm install --save @ionic-native/firebase
npm install --save angularfire2 firebase

Now import them in your app.module.ts.

import { Firebase } from '@ionic-native/firebase';

import { AngularFireModule } from 'angularfire2';
import { AngularFirestoreModule } from 'angularfire2/firestore';

const config = {
// your firebase web config
}

@NgModule({
imports: [
// ...
AngularFireModule.initializeApp(config),
AngularFirestoreModule,
],
providers: [
// ...
Firebase,
FcmProvider,

]
})

You can get the config file in your https://console.firebase.google.com/. Click on Add another app and then click on Add Firebase to your web app.

Step 3

Register your iOS and android device with Firebase. Click on Add Firebase to your Android/iOS app. You can get/change the package name from your config.xml file of your ionic project.

Type in your package name and click Register app. Now download the google-services.json file and keep it in the root of your ionic project.

If you had clicked for iOS, you will get a GoogleService-Info.plist instead of the json file.

Step 4

Generate a firebase cloud messaging provider that we will be using in our app.

ionic generate provider fcm

Now let’s write the provider code which will be responsible for sending notifications to the firebase cloud. Copy the below code to fcm.ts provider.

// fcm.ts

import { Injectable } from '@angular/core';
import { Firebase } from '@ionic-native/firebase';
import { Platform } from 'ionic-angular';
import {HttpClient, HttpHeaders} from '@angular/common/http';

@Injectable()
export class FcmProvider {

constructor(private platform: Platform,
public firebaseNative:Firebase,
public http: HttpClient) {
console.log('Hello FcmProvider Provider');
}

// Get permission from the user
async getToken() {
let token;

if (this.platform.is('android')) {
token = await this.firebaseNative.getToken()
}

if (this.platform.is('ios')) {
token = await this.firebaseNative.getToken();
await this.firebaseNative.grantPermission();
}
// Post the token to your node server
this.http.post("http://<ip_address_of_node_server>:3000/store", token)
.subscribe(data => {
console.log(JSON.stringify(data));
}, error => {
console.log("err");
console.log(JSON.stringify(error));
});
}

// Listen to incoming FCM messages
listenToNotifications() {
return this.firebaseNative.onNotificationOpen()
}
}

We want to extract the token and send it to the server once the app is opened. So copy the below code to app.component.ts

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import {TabsPage} from "../pages/tabs/tabs";
import { FcmProvider } from '../providers/fcm/fcm';
import { ToastController } from 'ionic-angular';
import { tap } from 'rxjs/operators';
import { Firebase } from '@ionic-native/firebase';

@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = TabsPage;

constructor(platform: Platform, statusBar: StatusBar,
splashScreen: SplashScreen, fcm: FcmProvider,
toastCtrl: ToastController,
public firebaseNative: Firebase) {
platform.ready().then(() => {

statusBar.backgroundColorByHexString('#2693ee');
statusBar.styleDefault();
splashScreen.hide();

// Get an FCM token
fcm.getToken();

// Listen to incoming messages
fcm.listenToNotifications().pipe(
tap(msg => {
// show a toast
const toast = toastCtrl.create({
message: msg.body,
duration: 3000
});
toast.present();
})
)
.subscribe();
});
}
}

Step 5

Now we are done with our app configurations. Let us build our node server which will

  • receive the devices’ token
  • store the tokens in a database
  • extract the existing tokens from database
  • send notifications to all of them

Create a folder named node-server and create a server.js file in it. Create an empty package.json file by typing the below command.

npm init

Copy the below contents to the package.json file and run npm install to install the dependecies.

{
"name": "node-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "node server.js",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.3",
"fcm-node": "^1.2.1",
"mongodb": "^3.1.0",
"request": "^2.87.0"
}
}

Step 6

Install and configure mongoDB in your system as per the official docs. Once you are done installing mongoDB, run it in shell using:

mongod

Create a new database:

use DATABASE_NAME

Step 7

Open up the server.js and import all the installed modules.

'use strict'

const express = require('express');
const app = express(),
request = require('request'),
mongo = require('mongodb'),
bodyParser = require('body-parser');

We will use bodyParser to parse the http response.

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.get('/', (req, res) => {
res.send('Notifications Test!');
});

Allow the CORS access control for testing in localhost. (Not for production)

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

Initialise your mongoDB database with node.

const MongoClient = mongo.MongoClient;
const url = 'mongodb://localhost:27017/DATABASE_NAME';
const dbName = 'DATABASE_NAME';

The post method to store the tokens to database.

app.post('/store', (req, res) => {

MongoClient.connect(url, (err, client) => {
if (err) throw err;
else {
let db = client.db(dbName);
db.collection('tokens').insertOne(req.body, (err, body) => {
if (err) throw err;
res.status(200).send('');
})
}
client.close();
});
});

Now, configure your Firebase Cloud Messaging configs.

var FCM = require('fcm-node');
var serverKey = 'ASDFASKH...'; //put your server key here
var fcm = new FCM(serverKey);

You can get the server key in your app settings -> Cloud Messaging

Now write your fcm get method which will be responsible to send messages to the firebase cloud and the later in turn will push notifications to your phone.

app.get('/send', function(req, res) {

var token_array = [];

MongoClient.connect(url, (err, client) => {
if (err) throw err;
else {
let db = client.db(dbName);
db.collection('tokens').find().toArray((err, docs) => {
if (err) throw err;
for(let i = 0; i < docs.length; i++) {
token_array.push(docs[i]);
}
});
}
client.close();
});

for(let i = 0; i < token_array.length; i++) {
var message = {
// this may vary according to the message type (single
// recipient, multicast, topic, et cetera)

to: token_array[i].token,
collapse_key: 'your_collapse_key',

notification: {
title: 'Title of your push notification',
body: 'Body of your push notification'
},

data: {
// you can send only notification or only
// data(or include both)
my_key: 'my value',
my_another_key: 'my another value'
}
};

fcm.send(message, function (err, response) {
if (err) {
console.log("Something has gone wrong!");
} else {
console.log("Successfully sent with response: ", response);
}
});
}
res.send('send msg');
});


app.listen(3000, () => console.log('Notifier listening on port 3000!'));

Step 8

Now install the app in your device by running:

ionic cordova run android

Once the app opens up, a token is sent to your local server and stored in your database. Now if you make a get request to the url: http://<ip_of_your_machine>:3000/send a notification will be sent to your device.

Note: Both the phone and your computer should be in the same network or-else, you have to use ngrok to expose your local server.

Github repo for this project: https://github.com/sr6033/node-ionic-notifications

--

--

Shubham Rath
hirewithparam

Software Engineer @ Goibibo. Writer in GeeksforGeeks. Former SDE @ param.ai. ACM ICPC Regionals 2018.