Search code examples
androidpush-notificationprogressive-web-apps

PWA stop receiving push notification on android app closed


I created a simple PWA application with a Service Worker that is receiving push notifications from my server when needed and show a notification for the user. This works great when the application is running on the foreground and when the application is on background for a few minutes, the push notification is received and shown to the user as intended. But passed a few minutes on background or if the app is closed, the PWA stop receiving these push notifications.

What I have so far:

service-worker.js

self.addEventListener('push', (e) => {
  let notificationData
  e.waitUntil(
    clients.matchAll({ type: 'window' }).then(function(clientList) {
      const client = clientList && clientList[0]
      if (e.data && client && client.visibilityState !== 'visible') {
        const envelope = e.data.json()
        // Process the notification
        // ...
        e.waitUntil(self.registration.showNotification(data.subject, options))
      }
    })
  )
})

index.js

  async registerPushNotificationToWorker() {
    if ('serviceWorker' in navigator) {
      try {
        const swRegistration = await navigator.serviceWorker.getRegistration()
        let subscription = await swRegistration.pushManager.getSubscription()
        let subscriptionJson
        if (subscription === null) {
          subscriptionJson = await subscribeUser()
        } else {
          subscriptionJson = subscription.toJSON()
        }
        // Save subscriptionJson on server
        // ...
      } catch (e) {
        console.log('Service Worker registration failed: ', e)
      }
    }
  }

  async subscribeUser() {
    if ('serviceWorker' in navigator) {
      const swRegistration = await navigator.serviceWorker.ready
      try {
        const pushSubscription = await swRegistration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey
        })
        return pushSubscription.toJSON()
      } catch (e) {
        console.log('Error', e)
        if (Notification.permission === 'denied') {
          console.warn('Permission for notifications was denied')
        } else {
          console.error('Unable to subscribe to push', e)
        }
      }
    }
    return null
  }

From what I understood, the service worker on android should be woken up when a push notification is received even if the app is closed. There is a specific code I should do for the service worker to be woken up when needed?


Solution

  • Found the problem. The problem here was the Event Listener on the service-worker was getting the clients to verify if the application was already open, but I was assuming there would always be a client on the list, even when the app is closed. The correct way would be something like:

    self.addEventListener('push', (e) => {
      let notificationData
      e.waitUntil(
        clients.matchAll({ type: 'window' }).then(function(clientList) {
          const client = clientList.find(c => c.visibilityState === 'visible') // <- This validation
          if (e.data && !client) {
            const envelope = e.data.json()
            // Process the notification
            // ...
            e.waitUntil(self.registration.showNotification(data.subject, options))
          }
        })
      )
    })