javascriptandroidweb-pushmobile-chromesamsung-internet

Push API: Mobile browsers don't receive push notifications anytime. Only when SW is running


I am developing a PWA with node.js. It is installable and it runs nicely.

Lately I tried to implement Push Notifications like explained here: https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push

This is the express route to trigger a notification for all subscriptions (only for testing purposes)

app.get('/notifyall/', function(req, res) {
  subscriptions.forEach(subObject => {
    webPush.sendNotification(subObject.sub, "notify All");
  })
  res.send("sent");
});

This is the eventhandler in the serviceworker

self.addEventListener('push', function(event) {
  const payload = event.data ? event.data.text() : 'no payload';
  console.debug("sw push event");

  event.waitUntil(
    self.registration.showNotification('ServiceWorker Cookbook', {
      body: payload,
      renotify: true,
      tag: 'test'
    })
  );
});

this is how I register a subscription to the push service

sub = navigator.serviceWorker.ready
    .then(function(registration) 
    {
      return registration.pushManager.getSubscription()
      .then(async function(subscription) 
      {
        console.debug("pwasetup: getSubscription");
        if (subscription) {
          console.debug("sub found");
          sub = subscription;
          return subscription;
        }

        const response = await fetch('/vapidPublicKey/');
        const vapidPublicKey = await response.text();
        // Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
        const convertedVapidKey = frontendfuncs.urlBase64ToUint8Array(vapidPublicKey);

        var newSub = registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: convertedVapidKey
        });
        console.debug("sub: " + JSON.stringify(newSub));
        return newSub;
      });
    })
    .then(function(subscription) 
    {
      // Send the subscription details to the server using the Fetch API.  
      console.debug("sub: " + JSON.stringify(subscription));

      Notification.requestPermission(function(result) 
      {
        if(result === "granted")
        {
          fetch('/register/', {
            method: 'post',
            headers: {
              'Content-type': 'application/json'
            },
            body: JSON.stringify({
              subscription: subscription
            }),
          });
        }
      })
    });
  });

I tested receiving push notifications with three different mobile browsers on my samsung galaxy S10+ in Chrome, Firefox and Internet (Samsung). (Of course in the installed/A2HS version of my app. The push notification was triggerd by the code in the /notifyall/ route, mentioned above)

When the app is open, or the sw still in running state, the notifcation is received and displayed without any problems. But after that things become less easy in Chrome for Android and Samsung Internet:

Chrome: Firing a notification like 2 minutes after app being closed, the notification will not be displayed, till I open the PWA again. (Bonus question: Why after 2 minutes? I thougt chrome closes sw after 30 seconds)

Internet (Samsung): After the sw is stopped, the notification arrives on display unlock. Not earlier.

Firefox: Seems to get the push notification at any time and displays it, as it should.

Does anyone know, what here the problems are in Chrome and Samsung Internet? I just want to notify my users anytime. Not at certain circumstances...

Thanks!


Solution

  • Problem solved. Easier than it sounds...

    Since the PWA needs to be installed/A2HS to use the feature of receiving notifications at any time, I tried to give all the needed settings to the PWA itself (notifications allowed, background optimization disabled, etc.).

    Therefore I never thought of, disabling background optimization for the browser-main-app too, which is necessary to wake up the serviceworker of the PWA.

    All three browsers work now as intended.