Wednesday, March 24, 2021

JavaScript: Firebase Configuration & Important REST API's Example



Configuration & Simple Example

How to configuration your apps, send message, validate registration id, manage topic, manage group, batch, etc with Firebase Cloud Messaging ?

  1. Step 1
    Register & Get Configuration from https://console.firebase.google.com/
  2. Step 2
    For simple examples: Create file index.html & firebase-messaging-sw.js
  3. Step 3
    Let's follow the code below

index.html

<!--
	Notification using Firebase Example
	-----------------------------------

	Step 1 : Create file index.html & firebase-messaging-sw.js
	Step 2 : Register & Get Configuration from https://console.firebase.google.com/
	Step 2 : You need to run this app at http://{host}
	Step 3 : Done

	-----------------------------------

	Reference :
		- https://firebase.google.com/docs/cloud-messaging/js/client?hl=id
		- https://www.youtube.com/watch?v=BsCBCudx58g
		- https://firebase.google.com/docs/cloud-messaging/http-server-ref?hl=id
		- https://medium.com/@selvaganesh93/firebase-cloud-messaging-important-rest-apis-be79260022b5
		- https://medium.com/@sachinkhard/send-push-notification-via-firebase-by-postman-3f459ea5d170
		- https://firebase.google.com/docs/cloud-messaging/android/device-group
		- https://stackoverflow.com/a/60247902/9278668
		- https://stackoverflow.com/a/51529975/9278668
-->
<html>
<head>
	<title>Notification using Firebase Example</title>
</head>
<body>
	<h1>Notification using Firebase Example</h1>

	<button onclick="uninstallServiceWorker()">Uninstall Service Worker</button>
	<button onclick="inspectServiceWorker()">Inspect Service Worker</button>

	<br /><br />

	Open : <a href="chrome://inspect/#service-workers">chrome://inspect/#service-workers</a> for <b>inspect</b> <i>service worker</i> in google chrome

</body>
</html>

<script src="https://www.gstatic.com/firebasejs/8.3.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.3.0/firebase-messaging.js"></script>

<script type="text/javascript">
let firebaseConfig = {
	apiKey: "{YOUR_FIREBASE_API_KEY}",
	authDomain: "{YOUR_FIREBASE_AUTH_DOMAIN}",
projectId: "{YOUR_FIREBASE_PROJECT_ID}",
storageBucket: "{YOUR_FIREBASE_STORAGE_BUCKET}",
messagingSenderId: "{YOUR_FIREBASE_SENDER_ID}",
appId: "{YOUR_FIREBASE_APP_ID}",
measurementId: "{YOUR_FIREBASE_MEASUREMENT_ID}"
}; // Initialize Firebase firebase.initializeApp(firebaseConfig); const messaging = firebase.messaging(); messaging.requestPermission() .then(function() { console.log('[BROWSER-FIREBASE] - Have permission'); return messaging.getToken(); }) .then(function(currentToken) { console.log('[BROWSER-FIREBASE] - Firebase Client Token :', currentToken); }) .catch(function(err) { console.log('[BROWSER-FIREBASE] - Error Occurred.', err); }); // Only on Window messaging.onMessage(function(payload) { console.log('[BROWSER-FIREBASE] - Received Foreground Message : ', payload); // https://stackoverflow.com/a/60247902/9278668 navigator.serviceWorker.getRegistration('/firebase-cloud-messaging-push-scope').then(registration => { let options = { body : payload.data.body, actions : JSON.parse(payload.data.actions), data : payload.data }; registration.showNotification( payload.data.title, options ) }); }); </script> <script type="text/javascript"> function uninstallServiceWorker() { if('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations().then(function(registrations) { for(let registration of registrations) { console.log('[BROWSER] - Uninstalled service worker successful.', registration); registration.unregister(); } }); } } function inspectServiceWorker() { alert('Open -> chrome://inspect/#service-workers'); window.location = 'chrome://inspect/#service-workers'; } </script>

firebase-messaging-sw.js

importScripts('https://www.gstatic.com/firebasejs/8.3.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.3.0/firebase-messaging.js');

let firebaseConfig = {
	apiKey: "{YOUR_FIREBASE_API_KEY}",
authDomain: "{YOUR_FIREBASE_AUTH_DOMAIN}",
projectId: "{YOUR_FIREBASE_PROJECT_ID}",
storageBucket: "{YOUR_FIREBASE_STORAGE_BUCKET}",
messagingSenderId: "{YOUR_FIREBASE_SENDER_ID}",
appId: "{YOUR_FIREBASE_APP_ID}",
measurementId: "{YOUR_FIREBASE_MEASUREMENT_ID}"
}; // Initialize Firebase firebase.initializeApp(firebaseConfig); const messaging = firebase.messaging(); messaging.onBackgroundMessage(function(payload) { console.log('[SERVICE-WORKER-FIREBASE] - Received Background Message : ', payload); // Customize notification here let options = { body : payload.data.body, actions : JSON.parse(payload.data.actions), data : payload.data }; return self.registration.showNotification(payload.data.title, options); }); // https://stackoverflow.com/a/51529975/9278668 self.addEventListener('notificationclick', (event) => { console.log('Event :', event); console.log('Event Action :', event.action); event.waitUntil(async function () { let clientList = await clients.matchAll({ includeUncontrolled: true }); console.log('clientList :', clientList); let currentClient; for (let client of clientList) { console.log('client :', client); if (client['url'].indexOf(event.notification.data.click_action) >= 0) { client.focus(); currentClient = client; break; } } if (!currentClient) { currentClient = await clients.openWindow(event.notification.data.click_action); } }()); });


Important REST API you need to know

  1. Send Notification
    URL : https://fcm.googleapis.com/fcm/send
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    Request Body :
    {
    	"data":{
    		"title":"New Text Message",
    		"body":"Hello how are you?",
    		"image":"https://firebase.google.com/images/social.png",
    		"icon":"https://firebase.google.com/images/favicon.png",
    		"badge":"https://firebase.google.com/images/favicon.png",
    		"meta":{
    			"type":"small",
    			"info":"Search"
    		}
    	},
    	"to":"{CLIENT_TOKEN_ID}"
    }
    
    Response :
    {
    	"multicast_id":4921980195954539141,
    	"success":1,
    	"failure":0,
    	"canonical_ids":0,
    	"results":[
    		{
    			"message_id":"0:1616595535458896%e609af1cf9fd7ecd"
    		}
    	]
    }
    

  2. Send Notification to Multiple Registration IDs
    URL : https://fcm.googleapis.com/fcm/send
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    Request Body :
    {
    	"data":{
    		"title":"New Text Message",
    		"body":"Hello how are you?",
    		"image":"https://firebase.google.com/images/social.png",
    		"icon":"https://firebase.google.com/images/favicon.png",
    		"badge":"https://firebase.google.com/images/favicon.png",
    		"meta":{
    			"type":"small",
    			"info":"Search"
    		}
    	},
    	"registration_ids":[
    		"{CLIENT_TOKEN_ID_1}",
    		"{CLIENT_TOKEN_ID_2}",
    		"{CLIENT_TOKEN_ID_3}",
    		"..."
    	]
    }
    Response :
    {
    	"multicast_id":4921980195954539141,
    	"success":1,
    	"failure":0,
    	"canonical_ids":0,
    	"results":[
    		{
    			"message_id":"0:1616595535458896%e609af1cf9fd7ecd"
    		}
    	]
    }
    

  3. Validate Registration ID
    URL : https://iid.googleapis.com/iid/info/{CLIENT_TOKEN}?details=true
    Method : GET
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    Response :
    {
    	"application":"com.chrome.windows",
    	"subtype":"wp:http://127.0.0.1/#CAE6289F-8CD2-4D33-8B18-A3C22E76B-V2",
    	"scope":"*",
    	"authorizedEntity":"1065953619143",
    	"platform":"BROWSER"
    }
    

  4. Create Group
    URL : https://fcm.googleapis.com/fcm/notification
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    - project_id : {YOUR_SENDER_ID}
    Request Body :
    {
    	"operation":"create",
    	"notification_key_name":"{YOUR_GROUP_KEY_NAME}",
    	"registration_ids":[
    		"{CLIENT_TOKEN_ID_1}",
    		"{CLIENT_TOKEN_ID_2}",
    		"{CLIENT_TOKEN_ID_3}",
    		"..."
    	]
    }
    Response :
    {
    	"notification_key":"{NOTIFICATION_KEY}"
    }
    

  5. Send Notification to Group
    URL : https://fcm.googleapis.com/fcm/send
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    Request Body :
    {
    	"data":{
    		"title":"New Text Message",
    		"body":"Hello how are you?",
    		"image":"https://firebase.google.com/images/social.png",
    		"icon":"https://firebase.google.com/images/favicon.png",
    		"badge":"https://firebase.google.com/images/favicon.png",
    		"meta":{
    			"type":"small",
    			"info":"Search"
    		}
    	},
    	"to":"{NOTIFICATION_KEY}"
    }
    Response :
    {
    	"success":3,
    	"failure":0
    }
    

  6. Create Topic
    URL : https://iid.googleapis.com/iid/v1:batchAdd
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    - Content-Type : application/json
    Request Body :
    {
    	"to":"/topics/YOUR_TOPIC_NAME",
    	"registration_tokens":[
    		"{CLIENT_TOKEN_ID_1}",
    		"{CLIENT_TOKEN_ID_2}",
    		"{CLIENT_TOKEN_ID_3}",
    		"..."
    	]
    }

  7. Remove Topic
    URL : https://iid.googleapis.com/iid/v1:batchRemove
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    - Content-Type : application/json
    Request Body :
    {
    	"to":"/topics/{TOPIC_NAME}",
    	"registration_tokens":[
    		"{CLIENT_TOKEN_ID_1}",
    		"{CLIENT_TOKEN_ID_2}",
    		"{CLIENT_TOKEN_ID_3}",
    		"..."
    	]
    }
    

  8. Send Notification to Topic
    URL : https://fcm.googleapis.com/fcm/send
    Method : POST
    Header :
    - Authorization : key={YOUR_SERVER_KEY}
    Request Body :
    {
    	"data":{
    		"title":"New Text Message",
    		"body":"Hello how are you?",
    		"image":"https://firebase.google.com/images/social.png",
    		"icon":"https://firebase.google.com/images/favicon.png",
    		"badge":"https://firebase.google.com/images/favicon.png",
    		"meta":{
    			"type":"small",
    			"info":"Search"
    		}
    	},
    	"to":"/topics/{TOPIC_NAME}"
    }
    Response :
    {
    	"message_id":{GENERATED_MESSAGE_ID}
    }
    

Note :

  1. iOS users receive notifications if it contains “notification” key and android users will receive notification for both notification and data key.
  2. iOS users will receive background notification if it contains both key value pair “content_available” : true and “priority” : “high”
  3. For iOS notification must contain keys title and body to receive notification

Reference :


Monday, March 15, 2021

Notification using Service Worker Example

 


How to create notification using Service Worker?

Let's follow the code below :

index.html

<!--
	Notification using Service Worker Example
	-----------------------------------

	Step 1 : Create file index.html & sw.js
	Step 2 : You need to run this app at http://{host}
	Step 3 : Done

	-----------------------------------

	Reference :
		- https://developers.google.com/web/fundamentals/primers/service-workers
		- https://stackoverflow.com/a/33705250/9278668
		- https://stackoverflow.com/a/31480604/9278668
		- https://serviceworke.rs/push-clients_service-worker_doc.html
		- https://css-tricks.com/creating-scheduled-push-notifications/
		- https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification
		- https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/message_event
-->
<html>
<head>
	<title>Notification using Service Worker Example</title>
</head>
<body>
	<h1>Notification using Service Worker Example</h1>

	<button onclick="installServiceWorker()">Install Service Worker</button>
	<button onclick="uninstallServiceWorker()">Uninstall Service Worker</button>
	<button onclick="inspectServiceWorker()">Inspect Service Worker</button>

	<button onclick="showNotification()">Show Notification</button>
	<button onclick="closeAllNotifications()">Close All Notifications</button>

	<br /><br />

	Open : <a href="chrome://inspect/#service-workers">chrome://inspect/#service-workers</a> for <b>inspect</b> <i>service worker</i> in google chrome

</body>
</html>

<script type="text/javascript">
function installServiceWorker() {
	if('serviceWorker' in navigator) {
		// Install Service Worker
		navigator.serviceWorker.register('./sw.js').then(function(registration) {
			console.log('[BROWSER] - Service worker registration successful with scope : ' + registration.scope);
		}, function(err) {
			console.error('[BROWSER] - Service worker registration failed :', err);
		});

		// Init to listen incoming message from service worker
		navigator.serviceWorker.addEventListener('message', function(event) {
			console.log('Event : ', event);
			console.log('postMessage : ', event.data);

			alert("Message from Service Worker :\n\n" + "postMessage : " + event.data + "\n\n" + "Event : " + JSON.stringify(event));
		});
	}
}
function uninstallServiceWorker() {
	if('serviceWorker' in navigator) {
		navigator.serviceWorker.getRegistrations().then(function(registrations) {
			for(let registration of registrations) {
				console.log('[BROWSER] - Uninstalled service worker successful.', registration);
				registration.unregister();
			} 
		});
	}
}
function inspectServiceWorker() {
	alert('Open -> chrome://inspect/#service-workers');
	window.location = 'chrome://inspect/#service-workers';
}
async function showNotification(title, body) {
	const reg = await navigator.serviceWorker.getRegistration();
	Notification.requestPermission().then(function(permission) {
		if (permission !== 'granted') {
			alert('You need to allow push notifications');
		}
		else {
			reg.showNotification(
				'Demo Push Notification', {
					tag: 'my-simple-notification-sw', // a unique ID
					body: 'Hello World', // content of the message notification
					data: {
						url: window.location.href, // pass the current url to the notification
					},
					badge: 'http://ahmbcode.id/img/logo.png',
					icon: 'http://ahmbcode.id/img/logo.png',
					image: 'http://ahmbcode.id/img/logo.png',
					vibrate: [500, 300, 500],
					silent: false,
					actions: [
						{
							action: 'open_google',
							title: 'Open Google',
							//icon:'http://ahmbcode.id/img/logo.png'
						},
						{
							action: 'open_gmail',
							title: 'Open Gmail',
							//icon:'http://ahmbcode.id/img/logo.png'
						}
					]
				}
			);
		}
	});
}

function closeAllNotifications() {
	navigator.serviceWorker.getRegistration().then(function(registration){
		registration.getNotifications().then(function(notifications){
			notifications.forEach(function(notification){
				notification.close();
			});
		});
	});
}
</script>

sw.js

self.addEventListener('install', function(event) {
	console.log('[SERVICE-WORKER] - Service worker installed successful.');
	event.waitUntil(self.skipWaiting());
});

self.addEventListener('activate', function(event) {
	console.log('[SERVICE-WORKER] - Service worker activated');
	event.waitUntil(self.clients.claim());
});

self.addEventListener('notificationclick', function(event) {

	console.log('[SERVICE-WORKER] - Notification Action : ', event.action);
	console.log('[SERVICE-WORKER] - Notification Data   : ', event.notification.data);

	// event.notification.close();

	if(event.action === 'open_google') {
		openPage('https://www.google.com', event);
	}
	else if(event.action === 'open_gmail') {
		openPage('https://mail.google.com', event);
	}
});

// Check the browser for update the current tab or open new tab
function openPage(url, event) {
	event.waitUntil(
		self.clients.matchAll().then(function(clientList) {
			
			if (clientList.length > 0) { // If Tab is currently open

				clientList[0].postMessage('Opening -> ' + url);	// Send data to Window

				clientList[0].navigate(url);		// Redirect URL in current tab
				return clientList[0].focus();		// Focus in current tab
			}

			// If Tab are closed
			return self.clients.openWindow(url);
		})
	);
}


You  need run this app on http://{host} .

For developer tools, you can inspect the service workers at chrome://inspect/#service-workers


Reference :