Search code examples
iosiphonemobileprogressive-web-apps

PWA IOS push notification shows when app is in foreground


I have a service worker that has a event listener for push messages.

Here is the code

self.addEventListener('push', (event) => {
  event.waitUntil(clients.matchAll({ type: 'window' }).then((clients) => {
    console.log('Push event 3', event.data.json())
    for (let i = 0; i < clients.length; ++i) {
      if (clients[i].visibilityState === 'visible') return // there is a visible window
    }
    // continue with showing a notification
    const data = notification.data || {}
    data.click_action = notification.click_action
    return registration.showNotification(notification.title + " test ", {
      body: notification.body,
      icon: notification.icon,
      badge: notification.badge,
      data: data,
      requireInteraction: true,
      actions: notification.actions,
      image: notification.image,
      click_action: notification.click_action
    })
  }))
})

async function checkClientIsVisible() {
  const windowClients = await clients.matchAll({
    type: 'window',
    includeUncontrolled: true
  })

  for (var i = 0; i < windowClients.length; i++) {
    if (windowClients[i].visibilityState === 'visible') {
      return true
    }
  }

  return false
}

The listener function checks if there are any windows/tabs showing the website in the scope of the sw.

It works fine on desktops pwa (windows/mac) and on android pwa too, but on IOS the push notification is showing even if the pwa window is in the foreground, what I want is that the notifications DO NOT appear when the pwa is in the foreground, only closed/background.

Thank you!


Solution

  • Well, after a 3 days research, seems like is not possible what I want, the PWA in IOS will always show the notification if the server has sent one.

    Apple developer site stats (https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_web_apps_and_browsers) Safari doesn’t support invisible push notifications. Present push notifications to the user immediately after your service worker receives them. If you don’t, Safari revokes the push notification permission for your site.

    With this in mind, I've "resolved" the issue keeping track of the browser visibility in the server side via websocket (since I was using signalr already):

    • Watch for the document visibilitychange and sending the visibility status and the push device token to the server
    • Save the device token and the current status in the server

    Doing this way, when I need to send a push notification, I filter out the device tokens that are registered as visible on the server side and I never send a notificaiton to those devices.