[PWA] Enable Push Notification in your web app

1. Clone the project:

git clone https://github.com/GoogleChrome/push-notifications.git

2. install the web server:

3. Open the web server, set app folder as current folder, toggle the switch button to restart the server.

Go localhost:8887 you will see the push noticifiation app.

4. Register the service worker: app/js/main.js

if ('serviceWorker' in navigator) {
  console.log('Service Worker is supported');
  navigator.serviceWorker.register('sw.js').then(function() {
    return navigator.serviceWorker.ready;
  }).then(function(reg) {
    console.log('Service Worker is ready :^)', reg);
      // TODO
  }).catch(function(error) {
    console.log('Service Worker error :^(', error);
  });
}

The sw.js is located in app folder.

5. Add code to sw.js

console.log('Started', self);

self.addEventListener('install', function(event) {
  self.skipWaiting();
  console.log('Installed', event);
});

self.addEventListener('activate', function(event) {
  console.log('Activated', event);
});

self.addEventListener('push', function(event) {
  console.log('Push message received', event);
  // TODO
});

There there is a service worker activate. the new servie worker will wait unit the old service worker removed from the browser(hard refersh / close the current tab and open a new one). 

In 'Install' event, we tell 

self.skipWaiting()

So once anything changed in the code, refresh the browser, new servie worker will replace the old one and start work.

6. Make a project on the Google developer console

For now, if you want to have push notifications on Chrome, you need to create a project on developer console. FireFox doesn't need to do that. And in the future, you won't need to do that, it will support by default.

Push notifications from a web app need a backend service to handle messaging. Chrome currently uses Google Cloud Messaging (GCM) for this, though the eventual goal is for Chrome and GCM to support the Web Push Protocol. Other browsers are free to use other services.

  • From the Google APIs list, select Google Cloud Messaging. And Enable it.
  • Enter the key name
  • Click create. get your key
  • Go to IAM & Admin, get the project number

7. Add a mainfest

A manifest is a JSON file that provides information about your web app, including Push Notifications configuration.

app/manifest.json:

{
  "name": "Push Notifications codelab",
  "gcm_sender_id": "593836075156"
}

"gcm_sender_id" is what you got "project number" before.

Link in index.html to mainfest.json:

<!DOCTYPE html>
<html>
<head>

  <title>Push Notification codelab</title>
  <link rel="manifest" href="manifest.json">
</head>

<body>

  <h1>Push Notification codelab</h1>

  <script src="js/main.js"></script>

</body>
</html>

8. Subscribe to Push Notifications

Modify the js/main.js:

'use strict';

if ('serviceWorker' in navigator) {
    console.log('Service Worker is supported');
    navigator.serviceWorker.register('sw.js').then(function() {
        return navigator.serviceWorker.ready;
    }).then(function(reg) {
        console.log('Service Worker is ready :^)', reg);
        reg.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) {
            console.log('endpoint:', sub.endpoint);
        });
    }).catch(function(error) {
        console.log('Service Worker error :^(', error);
    });
}

This code uses the ServiceWorkerRegistration object's pushManager to subscribe to messages for the gcm_sender_id you added to the manifest previously.

You must pass a {userVisibleOnly: true} argument to the subscribe() method. This tells the browser that a notification will always be shown when a push message is received. Currently it's mandatory to show a notification.

9. Refresh your browser and you will see:

And you can find you "endPoint" in you console.

10. Send a request from the command line for GCM to push a message.

To get GCM to push a notification to your web client, you need to send GCM a request that includes the following:

    • The public API key that you created, which looks like this:

      AIzaSyAc2e8MeZHA5NfhPANea01wnyeQD7uVY0c

      GCM will match this with the Project Number you got from the Google Developer Console to use as thegcm_sender_id value in the manifest.
    • An appropriate Content-Type header, such as application/json.
    • An array of subscription IDs, each of which corresponds to an individual client app. That's the last part of the subscription endpoint URL, and looks like this: 

      APA91bHMaA-R0eZrPisZCGfwwd7z1EzL7P7Q7cyocVkxBU3nXWed1cQYCYvFglMHIJ40kn-jZENQ62UFgg5QnEcqwB5dFZ-AmNZjATO8QObGp0p1S6Rq2tcCuUibjnyaS0UF1gIM1mPeM25MdZdNVLG3dM6ZSfxV8itpihroEN5ANj9A26RU2Uw

Put together: (You need to get your own key, this would NOT work for you)E

curl --header "Authorization: key=AIzaSyAVOc3rC1jBZQ5AHg0_0mZjJ6GzgZiiZD" --header "Content-Type: application/json" https://android.googleapis.com/gcm/send -d "{"to":"cHOJzWtzgqQ:APA91bG6n-paaecj4CmGygeKrr2u7XX_0iOMM4kPNZz9YiZhpXyAMuy0dhtw_shqNtNyeU9HN5v2eGtrfW6nyCBEDm7ZdoOPi2k6q3LhCilw3JCrhmBpa8PIlcPQZmHFQF68dvR41tWN"}"

install cURL and try the command.

You will send the notificaiton in your browser.

But really, this is not useful, we want the custom message

10. Show the message:

in sw.js:

console.log('Started', self);

self.addEventListener('install', function(event) {
    self.skipWaiting();
    console.log('Installed', event);
});

self.addEventListener('activate', function(event) {
    console.log('Activated', event);
});

self.addEventListener('push', function(event) {
    console.log('Push message', event);

    var title = 'Push message';

    event.waitUntil(
        self.registration.showNotification(title, {
            body: 'The Message',
            icon: 'images/icon.png',
            tag: 'my-tag'
        }));
});

Try again, you will see:

Better, icon, title and message body.

11. Handle notification clicks

In this step you will add code to enable an action (such as navigating to a web page) when a user clicks a notification.

self.addEventListener('notificationclick', function(event) {
  console.log('Notification click: tag', event.notification.tag);
  // Android doesn't close the notification when you click it
  // See http://crbug.com/463146
  event.notification.close();
  var url = 'https://youtu.be/gYMkEMCHtJ4';
  // Check if there's already a tab open with this URL.
  // If yes: focus on the tab.
  // If no: open a tab with the URL.
  event.waitUntil(
    clients.matchAll({
      type: 'window'
    })
    .then(function(windowClients) {
      console.log('WindowClients', windowClients);
      for (var i = 0; i < windowClients.length; i++) {
        var client = windowClients[i];
        console.log('WindowClient', client);
        if (client.url === url && 'focus' in client) {
          return client.focus();
        }
      }
      if (clients.openWindow) {
        return clients.openWindow(url);
      }
    })
  );
});

This code listens for a notification click, then opens a web page — in this example, a YouTube video.

This code checks all window clients for this Service Worker; if the requested URL is already open in a tab, focus on it — otherwise open a new tab for it.

12. Unsubscribe from notifications

a client unsubscribes from notifications by calling the unsubscribe() method of the PushSubscriptionobject.

Modify the index.html add 

<!DOCTYPE html>
<html>
<head>

  <title>Push Notification codelab</title>

  <link rel="manifest" href="manifest.json">

</head>

<body>

<h1>Push Notification codelab</h1>

<p>This page must be accessed using HTTPS or via localhost.</p>

<button disabled>Subscribe</button>

<script src="js/main.js"></script>

</body>
</html>

Add a Subscribe/Unsubscribe button to your app.

Modify the main.js:

var reg;
var sub;
var isSubscribed = false;
var subscribeButton = document.querySelector('button');

if ('serviceWorker' in navigator) {
    console.log('Service Worker is supported');
    navigator.serviceWorker.register('sw.js').then(function() {
        return navigator.serviceWorker.ready;
    }).then(function(serviceWorkerRegistration) {
        reg = serviceWorkerRegistration;
        subscribeButton.disabled = false;
        console.log('Service Worker is ready :^)', reg);
    }).catch(function(error) {
        console.log('Service Worker Error :^(', error);
    });
}

subscribeButton.addEventListener('click', function() {
    if (isSubscribed) {
        unsubscribe();
    } else {
        subscribe();
    }
});

function subscribe() {
    reg.pushManager.subscribe({userVisibleOnly: true}).
    then(function(pushSubscription){
        sub = pushSubscription;
        console.log('Subscribed! Endpoint:', sub.endpoint);
        subscribeButton.textContent = 'Unsubscribe';
        isSubscribed = true;
    });
}

function unsubscribe() {
    sub.unsubscribe().then(function(event) {
        subscribeButton.textContent = 'Subscribe';
        console.log('Unsubscribed!', event);
        isSubscribed = false;
    }).catch(function(error) {
        console.log('Error unsubscribing', error);
        subscribeButton.textContent = 'Subscribe';
    });
}

In this code, you set the value of the ServiceWorkerRegistration object reg when the Service Worker installs, which is then used in the subscribe() function to subscribe to push messaging.

Everytime you subscribe and unsubscribe, the endpoint will change, so you need to reconfig it.

The subscribe() function creates the PushSubscription object sub which can be used by theunsubscribe() function.

Remember, the client gets a new registration ID every time it re-subscribes, so you will need to adjust requests to GCM accordingly.

 13. Add Actions Button to the notification:

//sw.js

self.addEventListener('push', function(event) {
    console.log('Push message', event);

    var title = 'Push message';

    event.waitUntil(
        self.registration.showNotification(title, {
            body: 'The Message',
            icon: 'images/icon.png',
            tag: 'my-tag',
            actions: [
                {action: 'like', title: 'Like', icon: 'images/like.png'},
                {action: 'setting', title: 'Setting', icon: 'images/setting.png'}
            ]
        }));
});

14. Handle action click:

According to different action type you can do different stuff, here just open different youtube video.

self.addEventListener('notificationclick', function(event) {
    console.log('Notification click: tag', event.notification.tag);
    event.notification.close();
    if(event.action === "like"){
        var url = "https://www.youtube.com/watch?v=DC8FsIdVi9Y";
    }else if(event.action === "setting"){
        var url = "https://www.youtube.com/watch?v=K9QY8faD6sY";
    }else{
        // Click the notification body
        var url = 'https://youtu.be/gYMkEMCHtJ4';
    }

    openWindow(event, url);
});

function openWindow(event, url){
    event.waitUntil(

        clients.matchAll({
            type: 'window'
        })
            .then(function(windowClients) {
                console.log('WindowClients', windowClients);
                for (var i = 0; i < windowClients.length; i++) {
                    var client = windowClients[i];
                    console.log('WindowClient', client);
                    if (client.url === url && 'focus' in client) {
                        return client.focus();
                    }
                }
                if (clients.openWindow) {
                    return clients.openWindow(url);
                }
            })
    );
}

15. Dismiss the notification:

If user click the close button, then it means user might not want to be distrubed. Then you might need to tell the server, not be send this user notification again.

self.addEventListener('notificationclose', function(event) {
    var data = event.notification.data;
    console.log('Notification Close', data);
    event.waitUntil(
        // Tell server not to send me notification again.
      //  fetch('/api/close-notif?id='+data.id)
    )
});
原文地址:https://www.cnblogs.com/Answer1215/p/5528583.html