Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly unregister service worker installed by firebase messaging

I am trying to implement a toggle to turn notifications on/off in a web app using Firebase messaging. My notifications work fine but there is a problem when a user tries to toggle off notifications. If I simply unregister the service worker via:

navigator.serviceWorker.getRegistrations().then((r) => {
  return Promise.all(r.map(reg => reg.unregister()));
});

then the worker does indeed get unregistered but if the user tries to turn notifications back on, Firebase will throw this error:

messaging/no-sw-in-reg

The error makes sense but there doesn't seem to be any built-in methods to unregister Firebase for users that no longer want it. Are you supposed to delete the firebase app and reinitialize it when/if the user asks for notifications again?

I realize that I could just delete the firebase token and forget about the user in my database but I do not want to leave a useless service worker that will never be called again.

What is the correct way to let a user disable firebase notifications completely in your web app?

like image 353
frboud Avatar asked Mar 23 '17 12:03

frboud


2 Answers

I have had the exact same problem. So I use your code to get rid of the service worker, and afterwards I reinitiate the messaging object, so you can unsubscribe and install the service worker again without reloading the page.

I found out this problem occures (at least in my code), because the messaging object caches the device token, so it won't trigger events that should be triggered when a device token is acquired. So re-initiating the messaging object is a viable option when you do not want to reload the page. Cleaning the messaging objects cache, would be an even better solution.

Example Code:

navigator.serviceWorker.getRegistrations().then((r) => {
   return Promise.all(r.map(reg => reg.unregister()));
});
this.messaging = firebase.messaging();

May the source be with you.

like image 121
mondjunge Avatar answered Oct 24 '22 09:10

mondjunge


In case is useful for someone else, instead of deactivate the whole ServiceWorker, is possible to only unsubscribe the PushNotifications.

By only unsubscribing from the PushSubscription, you also avoid the need of reassign the messaging property.

This is how I'm unsubscribing:

/*
Returns a Promise that resolves on the PushSubscription object that controls the push notification subscription, after it finds the coresponding ServiceWorker
*/
getSubscription() : Promise<any>{
    if(!navigator) return;

    const subscriptions = navigator.serviceWorker.getRegistrations().then((r) => {
      return r.map((sw) =>{
        if(!(sw.active && sw.active.scriptURL.includes("firebase-messaging")))
          return Promise.resolve();
        return sw.pushManager.getSubscription();

      });
    });

    return subscriptions.then(arr => arr ? arr[0] : Promise.resolve(null));
  }

===========================================================================

// Unsubscribes PushNotifications
rejectPermission() : Promise<boolean>{
    return this.getSubscription().then((pushSubscription : PushSubscription) =>{
      return pushSubscription.unsubscribe();
    });
  }

That's what I'm doing for my app and everything seems to work fine.

like image 2
Uriel Hernández Avatar answered Oct 24 '22 09:10

Uriel Hernández