Skip to Content
Technical Articles
Author's profile photo Dries Van Vaerenbergh

SAPUI5 Applications with Firebase Cloud Messaging

Hi there!

Nice to see you back, means you made it through to authentication part. Awesome!

If you didn’t, feel free to continue reading this blog or go 1 step back and check out the authentication part.

SAPUI5 FIREBASE BLOG SERIES:

Create SAPUI5 Applications with Google Firebase
SAPUI5 Applications with Firebase Anonymous Authentication
SAPUI5 Applications with Firebase Cloud Messaging (this blog)
Make SAPUI5 Firebase Applications Fiori Launchpad Ready

Like I mentioned in the previous blog we added the authentication part.

Now we can ask logged in users for permission to send notifications to their browser.

Now we want to receive notifications about shipments. We want to receive the notifications when we are focused on the application, but also when we are working in other tabs in the browser.

Actually we are all wandering how to do this. So let me stop explaining why why why, because we all know our own requirements on when to use them. In this case I only can say one thing….

 

Let’s get started!

We will be going through a few steps by writing some code and adding some files.

Some parts could be a little bit hard to understand, but don’t worry. Everything you need to know is explained in detail:

 

Alright all information sharing set and good to go!

 

1. Add the Firebase Cloud Messaging JS SDK

This messaging SDK will be added in our index.html file. In here we also imported our Firebase-app, Firestore and Authentication SDK’s.

Add the following messaging sdk:

<!-- Add the Firebase Messaging JS SDK -->
<script src="https://www.gstatic.com/firebasejs/6.2.0/firebase-messaging.js"></script>

 

 

2. Add the Google Cloud Messaging Sender id

We add this sender id right into our manifest.json file at the top. (you can use this id)

"gcm_sender_id": "103953800507",

This id can be found on Set up a JavaScript Firebase Cloud Messaging client app.

 

 

3. Create the firebase-messaging-sw.js file

This is a service worker file that will be searched for by the messaging service.

Place it in the root of your folder structure:

In here we will do a few things:

  • Import the required firebase-app and messaging service for the service worker.
  • Add our firebase-config again and initialize it.
  • Create a FCM reference.

Your firebase-messaging-sw-js file should look like this:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/6.2.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.2.0/firebase-messaging.js');

const firebaseConfig = {
	apiKey: "YOUR-API-KEY",
	authDomain: "YOUR-AUTH-DOMAIN",
	databaseURL: "YOUR-DATABASE-URL,
	projectId: "YOUR-PROJECT-ID",
	storageBucket: "YOUR-STORAGE-BUCKET,
	messagingSenderId: "YOUR-MESSAGE-SENDER-ID",
	appId: "YOUR-APP-ID"
};

firebase.initializeApp(firebaseConfig);

//FCM Reference
const messaging = firebase.messaging();

Now this file has been created and the firebase config is initialized we are all set and done so far.

 

 

4. Set the Messaging Reference in the Firebase.js file

Like we added the Firestore and Authentication reference before, we now want to add the messaging reference in the Firebase.js file. We do this likes so:

// Create a FCM reference
const messaging = firebase.messaging();
			
// Firebase services object
const oFirebase = {
	firestore: firestore,
	fireAuth: fireAuth,
	fcm: messaging
};

Now we can access our messaging service through our firebaseModel.

 

 

5. Request permission to send Notifications

We ask this permission in the Component.js file. This in our earlier created onAuthStateChanged observer.

We do this in the onAuthChanged obserever when we are logged in. So only logged in users can give us the permission and therefore we will only send shipment related notifications to logged in users.

The first thing we need to do is bind ‘this’ to our observer:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
    var isAnonymous = user.isAnonymous;
    var uid = user.uid;
    console.log("User: ", user);
  } else {
    // User is signed out.
  }
}.bind(this));

This because we will use the this reference in our observer.

 

The next thing we want to do is request the permission.

  • Get the messaging reference from the ‘firebaseModel’ by its property. (this is where and why we bound ‘this’ to our observer.
  • We ask the permission and log that we have permission if we have permission.
  • If we have permission we will get a FCM messaging token and logged it to the console.

Like this (inside the if(user) statement):

// CLOUD MESSAGING FCM
// Since we are logged in now we will ask the user permission to send notifications
// Create a FCM reference
const messaging = this.getModel("firebase").getProperty("/fcm");

//FCM ask permission
messaging.requestPermission().then(function () {
	console.log("Have permission");
	return messaging.getToken();
}).then(function (token) {
	console.log(token);
}).catch(function (err) {
	console.log("Error occured");
});

 

 

6. Receive Notifications in the Foreground

So now we have our token, we can do whatever we want with a message we receive, by adding the onMessage function. Still in the Component.js file under the requestPermission function.

This function will handle notifications on the foreground. So when we are focused on the tab with our app. In some cases you do not want to show notifications when in foreground or handle this incoming message in a different way. Whatever you want to do with it, this happens in the onMessage function. So the foreground handler.

 

In this case we will just show the notification anyway.

  • Parse the received JSON payload.
  • Log the received message to the console.
  • Get the title and the notifications options
  • Create a new Notification object with the title and options attributes.
  • Return the notification.

This by adding the following code:

// Show message in foreground (if desired)
messaging.onMessage(function (payload) {
	console.log("Message received. ", payload);
	var notification = JSON.parse(payload.data.notification);
	const notificationTitle =notification.title;
	const notificationOptions = {
		body: notification.body,
		icon: notification.icon,
	};
	var notification = new Notification(notificationTitle, notificationOptions);
	return notification;
});

When we now send notifications the message will be showed on the foreground.

 

So your full Component.js file init function should look like this:

init: function () {
	// call the base component's init function
	UIComponent.prototype.init.apply(this, arguments);

	// enable routing
	this.getRouter().initialize();

	// set the device model
	this.setModel(models.createDeviceModel(), "device");

	// Import Firebase in the sap.ui.define
	// set the firebase model by calling the initializeFirebase function in the Firebase.js file
	this.setModel(Firebase.initializeFirebase(), "firebase");

	// AUTHENTICATION
	// Create a Fireauth reference
	const fireAuth = this.getModel("firebase").getProperty("/fireAuth");

	// Login the user anonymously
	fireAuth.signInAnonymously().catch(function (error) {
		// Handle Errors here.
		var errorCode = error.code;
		var errorMessage = error.message;
	});

	// If the signInAnonymously method completes without error, the observer registered in the onAuthStateChanged 
	// will trigger and you can get the anonymous user's account data from the User object:
	fireAuth.onAuthStateChanged(function (user) {
		if (user) {
			// Example of accessible properties 
			var isAnonymous = user.isAnonymous;
			var uid = user.uid;
			console.log("User: ", user);

			// CLOUD MESSAGING FCM
			// Since we are logged in now we will ask the user permission to send notifications
			// Create a FCM reference
			const messaging = this.getModel("firebase").getProperty("/fcm");

			//FCM ask permission
			messaging.requestPermission().then(function () {
				console.log("Have permission");
				return messaging.getToken();
			}).then(function (token) {
				console.log(token);
			}).catch(function (err) {
				console.log("Error occured");
			});

			// Show message in foreground (if desired)
			messaging.onMessage(function (payload) {
				console.log("Message received. ", payload);
				var notification = JSON.parse(payload.data.notification);
				const notificationTitle =notification.title;
				const notificationOptions = {
					body: notification.body,
					icon: notification.icon,
				};
				var notification = new Notification(notificationTitle, notificationOptions);
				return notification;
			});
		} else {
			// User is signed out.
		}
	}.bind(this));

}

 

 

 

7. Receive Notifications in the Background

To receive notifications in the background (while not focused in the app on the current tab, or with the browser minimized) we need to update the firebase-messaging-sw-js file.

This by adding setBackgroundMessageHandler function.

This function handles obviously the in background received messages.

  • We log the notification to the console.
  • We parse the content.
  • set the title and the options.
  • Return the Notification by calling the self.registartion.showNotification. (default browser function to show notifications)
// Enable background messaging handler
messaging.setBackgroundMessageHandler(function (payload) {
	console.log("Message received in background. ", payload);
	
	// Retrieve data from the notification
	var notification = JSON.parse(payload.data.notification);
	const notificationTitle = notification.title;
	const notificationOptions = {
		body: notification.body,
		icon: "/webapp/" + notification.icon
	};

	// Show the notification with the params
	return self.registration.showNotification(notificationTitle,
		notificationOptions);
});

As you can see for the icon property we added a prefix. This prefix is used to build our path to the image that we want to show in our notification.

Later when we send a message we will add the image name to our payload.

But we need to add the image id to our webapp folder.

So place it right here:

 

 

8. Get you Server Token

To send a notification you will need a server token, this server token can be found in the Firebase console. This under project settings -> Cloud Messaging -> Server token.

 

 

9. Get your Receiver Token

Next you need a receiver, this receiver token is the token logged when you requested one in the Component.js file. Remember the code:

//FCM ask permission
messaging.requestPermission().then(function () {
	console.log("Have permission");
	return messaging.getToken();
}).then(function (token) {
	console.log(token);
}).catch(function (err) {
	console.log("Error occured");
});

So this token is the token which you send to.

So let’s get this token. Time to run the app.

When you run the app the app will ask your permission to send notifications. We will allow of course.

Next we open the console we will see we have permission to send notifications and our receiver token is logged.

(I hid a part of the key, it is a longer key than what you see)

 

 

10. Send a Notification

Sending notifications can be done in multiple ways.

You can send them for example by using:

  • CURL command
  • Postman

Here is a CURL example:

  • Change the  YOUR-SERVER-TOKEN to your server token from the Firebase console.
  • Change the YOUR-RECEIVER-TOKEN to your receiver token from the Chrome console.
  • Set the name of the image in the icon to the name of the image you uploaded in you webapp folder.
curl --header "Authorization: key=YOUR-SERVER-TOKEN" --header Content-Type:"application/json" -d "{\"to\":\"YOUR-RECEIVER-TOKEN\",\"data\":{\"notification\": {\"title\":\"Shipment lost\",\"body\":\"A shipment of Brussels just got lost.\",\"icon\":\"shipment.png\"}}}" https://fcm.googleapis.com/fcm/send

You can also add the notification to the root JSON structure. But then the messages will only be displayed in the onMessage function. So it will always think it should be handled as a foreground message. By adding the data property it knows when the app is in the background, this backgroundhandler needs to take over. But then the value of the data property is handled as a string. That’s why we parse it.

 

Run the CURL command in a terminal and see the notifications arrive in the foreground and background! 🙂

FOREGROUND NOTIFICATION RECEIVED:

BACKGROUND NOTIFICATION RECEIVED:

 

 

Demo action time! 

 

Recap time, what did we learn? 

In this blog we added the Firebase Cloud Messaging Service to our UI5 Application.

So here are some key takeaways:

  1. We need to add the the messaging service to our app.
  2. A service worker file called “firebase-messaging-sw.js” needs to be created.
  3. Receiving Notifications in the foreground and background need to be handled in a different way.
  4. How to send Notifications to clients.

 

Thanks for reading my blog about “SAPUI5 Applications with Firebase Cloud Messaging“.

I hope you found it interesting and it can serve your requirements!

Kind regards,

Dries

 

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Gopal Anand
      Gopal Anand

      Hi Dries Van Vaerenbergh ,

      I am getting the following error:

      A bad HTTP response code (404) was received when fetching the script.
      Component.js:38 err occured- FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. (messaging/failed-serviceworker-registration).
          at https://www.gstatic.com/firebasejs/6.2.0/firebase-messaging.js:1:31246

      not sure what can be the reason. In Networks, I can see firebase-messaging-sw.js getting loaded, The model is getting created, and permission is granted, while trying to get the token, it's throwing this error.

      Also in the manifest.json of my ui5 app, i am getting error message saying: "Property gcm_sender_id is not allowed."

      What can be the possible reasons for it?

       

      Author's profile photo Dries Van Vaerenbergh
      Dries Van Vaerenbergh
      Blog Post Author

      Hi Gopal Anand ,

      Did you put the gcm_sender_id at the top of your manifest.json like int the printscreen attached?

      Did you put the service worker file at the right directory in the app like I mentioned in the blog?

      If you did both of the above steps correctly my last question is the following:

      How are you running the app? As a web application or as a SAP Fiori Launchpad Sandbox?

      If you are running it as a SAP Fiori Launchpad Sandbox, can you try running as a web application?

      I saw that these error occurs indeed when running as a SAP Fiori Launchpad Sandbox application. That’s why I created my most recent Firebase blog to solved these issues. But if this is indeed the problem I should mention this too in this blog.

      Please keep me posted and thank you for your reaction!

      Kind regards,

      Dries

       

       

      Author's profile photo Gopal Anand
      Gopal Anand

      Hi Dries Van Vaerenbergh ,

      I Am running the application on cloud foundry using the application router.

      The normal approach to run the app as webapp, placing the firebase-messaging-sw.js file at root worked well.

      When I linked the application to app router for authentication and to call the backend services, the service worker file us getting a 404.

      That makes sense because the file is being searched at the root of the running app. which is the app router.

      It looks like this:

      Normal webapp deployment- appname.cfapp.com/firebase-messaging-sw.js(it’s working).

      Using application router :

      URL to run the app is: approuter.cfapps.com/ui_app_endpoint/webapp/index.html

      URL, where the firebase-messaging-sw.js file is searched, is: approuter.cfapps.com/ firebase-messaging-sw.js

      Clearly, the file cannot be found there. I have tried to manually call it in index.html using script tag:

      <script src="firebase-messaging-sw.js" type="text/javascript"></script>

      also, i tried register using navigator and following error occurred:

      errors.ts:136 Overwriting FirebaseError base field “name” can cause unexpected behavior.

      When I try to have the local copy of library and define it in the manifest i'm getting the following error:

      ReferenceError: firebase is not defined

      Mismatched anonymous define() module: function () { "use strict";

       

      Can you please suggest any solution.

      Best regards,

      Gopal

      Author's profile photo Dries Van Vaerenbergh
      Dries Van Vaerenbergh
      Blog Post Author

      Hi Gopal Anand ,

      I didn't have the time yet to look at it, but I plan to do so.

      Once I had a look at it, I'll let you know. (I really want to make it work on CF too.)     🙂

      Kind regards,

      Dries

      Author's profile photo Sandeep Roy
      Sandeep Roy

      Hi Dreis van,

       

      Thank you for your blog explained nicely. I am trying to setup bidirectional communication  betweeen my android app using Firebase messaging with my SAP UI 5 App. Is it possible to send notification from a SAP UI 5 app to Android App without using firebase database? I am looking forward to your answer.

       

      Thanks & Regards

      Sandeep Roy

      Author's profile photo Dries Van Vaerenbergh
      Dries Van Vaerenbergh
      Blog Post Author

      Hi Roy,

      Thanks for your reaction.

      This would be possible indeed.

      What you can do is use your Android app and subscribe to a topic using Firebase Cloud Messaging.

      Next you can create your UI5 Application and send a message to the topic you specify.

      To send to topics from web apps:

      https://firebase.google.com/docs/cloud-messaging/js/topic-messaging

      You can test the message sending with:

      https://firebase.google.com/docs/cloud-messaging/android/send-with-console

      This way the app which subscribed to the topic will receive the message.

      Subscribe android app to topic:

      https://firebase.google.com/docs/cloud-messaging/android/topic-messaging

       

      So this would be possible. 🙂

       

      Kind regards,

      Dries