Add push-notification service to Angular 6.1 in Cordova by using Laravel notification/queue and Firebase cloud messaging

Sometimes each developer faced a challenge to how to set up push notification for his app. In this article, we will talk about how to do this with Angular 6.1 application wrapped with Cordova and by using Laravel backend with firebase cloud messaging. This implementation only for Android but should work for IOS as well with an additional effort which is not covered in this article.

As a result, we can send test HTTP request to our backend via Postman and see the push-notification and email only for a specific user

How it should work schematically

Logically we can split all things in to buckets:

  1. Backend logic for creating and sending notifications due to our Business Logics
  2. Frontend logic for recieving push notification in our mobile app

1. Backend logic

We have to setup two threads. Thread number 1 will do our business logic and send task to table ‘job’ in our database via laravel notification. For this purpose we will use systemctl to run background task:

Our first service/thread config file:
/etc/systemd/system/notification.service

[Unit]
Description=Notifier
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/www/api-server-laravel
ExecStart=/usr/bin/php /var/www/api-server-laravel/artisan notificationmanager:run
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target

in order to start:

systemctl enable notification.service
systemctl start notification.service

Command code:

class AlarmsNotificationCommand extends ConsoleCommand
{

/**
* The name and signature of the console command.
*
*
@var string
*/
protected $signature = 'notificationmanager:run';

/**
* The console command description.
*
*
@var string
*/
protected $description = 'Just saying Welcome.';

/**
* Create a new command instance.
*
*
@return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
*
@return void
*/
public function handle()
{
$this->line('Starting single thread to check smt every 3 sec');
$last_id = 0;
while (true) {
try {
// DO SOMETING ENDLESSLY
$user = User:find(1);
Notification::send($user, new OurNotification('OK TEST'));
} catch (Exception $exception) {
$this->error($exception->getMessage());
}
sleep(3);
}
}
}

It’s just work perfect and you can test it by using email notification first. However, we are interesting in sending push notification and for this purposes we can use following laravel package: https://github.com/benwilkins/laravel-fcm-notification.

Our notification class:

class OurNotification extends Notification implements ShouldQueue
{
use Queueable;
/**
* @var \App\Containers\User\Models\User
*/
// protected $user;
protected $notificationMessage;
/**
* UserRegisteredNotification constructor.
*
* @param \App\Containers\User\Models\User $user
*/
public function __construct($notificationMessage)
{
$this->notificationMessage = $notificationMessage;
}
// which channel will we use for each notification
public function via($notifiable)
{
return [‘mail’, ‘database’,’fcm’];
}
// implementation for database
/**
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
‘content’ => $this->notificationMessage,
];
}
// implementation for mail
public function toMail($notifiable)
{
// $notifiable is the object you want to notify “e.g. user”
return (new MailMessage)
->subject(“Сообщение от ЛК”)
->line(“Добрый день, $notifiable->name”)
->line($this->notificationMessage);
}
// implementation for pushNotification
public function toFcm($notifiable)
{
$message = new FcmMessage();
$message->content([
‘title’ => ‘Сообщение от ЛК’,
‘body’ => $this->notificationMessage,
‘sound’ => ‘’, // Optional
‘icon’ => ‘notification_icon’, // Optional
‘click_action’ => ‘’ // Optional
])->data([
‘param1’ => ‘baz’ // Optional
])->priority(FcmMessage::PRIORITY_HIGH); // Optional — Default is ‘normal’.
return $message;
}
}

Now then the script execute Notification::send function, laravel will add job in our table with same name ‘jobs’, in order to start execute jobs in background we have to setup systemctl separate process or processes, example of service/thread2:
/etc/systemd/system/queue.service:

[Unit]
Description=Queue
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/www/api-server-laravel
ExecStart=/usr/bin/php /var/www/api-server-laravel/artisan queue:work --tries=50
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target

in order to start:

systemctl enable queue.service
systemctl start queue.service

If your user has email field in DB table user and you setup the config/mail.php (how to setup with gmail) its should work! Your Business logic send job to the table Jobs in Thread 1, Thread 2 pickup the task and by using

public function via($notifiable)
{
return [‘mail’];
}

sending email to logged user;

2. Frontend logic and a little bit more for backend

This part is a bit more complicated, especially for me, but let’s get started.
If we implement our backend with FCM support we have to clarify how to send a notification to the particular user or to be precise to a particular device.
By using our cordova/angular 6.1 application (finally we have to update our app to 6.1 to support typescript to 2.9 and other dependencies ) we have to generate google-service.json inside firebase dashboard: How to.
And setup api-key at laravel backend in: config/service.php :

'fcm' => [
'key' =>env('FCM_KEY'),
],

You can find the FCM KEY in firebase dashboard:

(gear-next-to-project-name) > Project Settings > Cloud Messaging

Server Key is the FCM key/API key.

When we have to put google-service.json in root of our cordova project and probably add line in config.xml

<resource-file src="google-services.json" target="google-services.json" />

Next thing that we have to add few cordova plugins and npm package

cordova add plugin cordova-plugin-fcm
cordova add plugin cordova-plugin-device
npm install @ionic-native/fcm

and one third party package:https://github.com/ercobo/angular-cordova in order to work with cordova in angular 6 app

Now let’s go to the code, first we have to get device token inside our app and send to our database, following code will figure it out:

import { Component, OnInit } from '@angular/core';import { FCM } from '@ionic-native/fcm';import { Cordova } from 'angular-cordova';import { UserService } from '../../_services';declare var device;@Component({selector: 'app-settings',templateUrl: './settings.component.html',styleUrls: ['./settings.component.scss']})export class SettingsComponent implements OnInit {public notification_support: boolean = false;constructor(public userService: UserService, public fcm: FCM, ) { }ngOnInit() {// Show that notification is ONif (localStorage.getItem('fcm_token')) {this.notification_support = true;}}// Action for buttonturnOnNotification() {Cordova.deviceready.subscribe((value) => {this.fcm.getToken().then(token => {console.log(token);// THIS METHOD WILL ADD USER TOKEN TO OUR BACKEND DB USER_DEVICESthis.userService.addToken(token, device.uuid, device.platform).subscribe((value) => {console.log('done');localStorage.setItem('fcm_token', token);this.notification_support = true;},(error) => { console.log('error'); });});});}}

This is how its should look like in our DB:

By using this tokens we can test our application at https://console.firebase.google.com/project/YOUR-PROJECT-NAME/notification

In our backend class Models/User.php we have to add additional method for pickup this tokens:

public function routeNotificationForFcm()
{
$user_id = $this['id'];

$user_tokens_array = GETTOKENS ARRAY FOR USER

return $user_tokens_array;
}

Now, we can enable FCM in our method

public function via($notifiable)
{
return [‘mail’,'fcm'];
}

Literally it’s done! Don’t forget to restart your systemctl services and laravel will send personal notification to yours Angular6.1/Cordova app

Hope, it was useful to read and if you have any questions, please don’t hesitate to leave a comment, since probably I forgot to mention something :-)

I am writing about my entrepreneurial journey as a full-stack developer and co-founder at Sensivo.eu. https://skob.io/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store