Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Web App User Interface when application is in background FCM

Tags:

Am using FCM to handle notifications, it works fine up until when I need to update my UI from the firebase-messaging-sw.js when my web app is in the background.

  1. My first question is: is it possible to update my web app UI in the background (When user is not focused on the web app) through a service worker

  2. Secondly, if so, how? because I tried a couple of things and its not working, obviously am doing something wrong and when it does work, my web app is in the foreground. What am I doing wrong?

My codes are below.

my-firebase-service-sw.js

// [START initialize_firebase_in_sw]
// 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/4.1.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.1.1/firebase-messaging.js');


// My Custom Service Worker Codes
var CACHE_NAME = 'assembly-v0.1.3.1';
var urlsToCache = [
    '/',
    'lib/vendors/bower_components/animate.css/animate.min.css',
    'lib/vendors/bower_components/sweetalert/dist/sweetalert.css',
    'lib/css/app_1.min.css',
    'lib/css/app_2.min.css',
    'lib/css/design.css'
];
var myserviceWorker;
var servicePort;


// Install Service Worker
self.addEventListener('install', function (event) {
    console.log('installing...');
   // Perform install steps
   event.waitUntil(
     caches.open(CACHE_NAME)
     .then(function (cache) {
     console.log('Opened cache');
     return cache.addAll(urlsToCache);
   })
   );
  console.log('installed...');
 });

  // Service Worker Active
  self.addEventListener('activate', function (event) {
  console.log('activated!');
  // here you can run cache management
  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function (cacheNames) {
       return Promise.all(
        cacheNames.map(function (cacheName) {
           if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
           }
        })
      );
    })
  );
});


self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)
      .then(function (response) {
        // Cache hit - return response
        if (response) {
          return response;
        }

        // IMPORTANT: Clone the request. A request is a stream and
        // can only be consumed once. Since we are consuming this
        // once by cache and once by the browser for fetch, we need
        // to clone the response.
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function (response) {
            // Check if we received a valid response
            if (!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

        // IMPORTANT: Clone the response. A response is a stream
        // and because we want the browser to consume the response
        // as well as the cache consuming the response, we need
        // to clone it so we have two streams.
        var responseToCache = response.clone();

        caches.open(CACHE_NAME)
          .then(function (cache) {
            cache.put(event.request, responseToCache);
          });

        return response;
      }
    );
  })
  );
});

self.addEventListener('message', function (event) {
  console.log("SW Received Message: " + event.data);
  // servicePort = event;
  event.ports[0].postMessage("SW Replying Test Testing 4567!");
});

myserviceWorker = self;


// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': '393093818386'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
// [END initialize_firebase_in_sw]

// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START background_handler]
messaging.setBackgroundMessageHandler(function (payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
 // Customize notification here
 // send to client
 console.log('Sending data to notification');
 try {
      myserviceWorker.clients.matchAll().then(function (clients) {
      clients.forEach(function (client) {
      console.log('sending to client ' + client);
      client.postMessage({
          "msg": "401",
          "dta": payload.data
      });
    })
  });
 } catch (e) {
    console.log(e);
 }
const notificationTitle = payload.data.title;;
const notificationOptions = {
   body: payload.data.body,
   icon: payload.data.icon,
   click_action: "value"
};

 return self.registration.showNotification(notificationTitle,
 notificationOptions);
});
// [END background_handler]

In my main javascript file, which receives the payload. it receives it when the application is in the foreground. My major concern and problem is receiving payload when the application is in the background, all activities on foreground works just fine.

like image 393
DaviesTobi alex Avatar asked Jul 18 '17 11:07

DaviesTobi alex


1 Answers

It is possible to update the UI even your website is opening but unfocused.
Just add enable option includeUncontrolled when you get all client list.
Example:

messaging.setBackgroundMessageHandler(function (payload) {
    console.log('[firebase-messaging-sw.js] Received background message ', payload);
    self.clients.matchAll({includeUncontrolled: true}).then(function (clients) {
       console.log(clients); 
       //you can see your main window client in this list.
       clients.forEach(function(client) {
           client.postMessage('YOUR_MESSAGE_HERE');
       })
     })
});

In your main page, just add listener for message from service worker.
Ex:

navigator.serviceWorker.addEventListener('message', function (event) {
    console.log('event listener', event);
});

See Clients.matchAll() for more details.

like image 154
user3444693 Avatar answered Oct 11 '22 13:10

user3444693