如何实现service worker



我已经通过不同的博客解释了service worker,其中一个是开放Web推送通知。我按照Open Web Push notification中的说明,实现了一个创建curl注册id的代码。一旦注册id被创建,我把它放在数据库中。但我没有收到任何通知。我通常在Google控制台启用GCM。我是否也应该编写gcm服务器和客户端代码,因为我读过很多博客,没有人说要这样做。我该怎么做才能收到通知。

如果我遗漏了什么,请参考下面的代码。

index.html

<!doctype html>
<html lang="en">
<head>
    <title>Push Messaging &amp; Notifications</title>
    <!-- Add to homescreen for Chrome on Android -->
    <meta name="mobile-web-app-capable" content="yes">
    <link rel="icon" sizes="192x192" href="../images/touch/chrome-touch-icon-192x192.png">
    <!-- Add to homescreen for Safari on iOS -->
    <meta name="apple-mobile-web-app-title" content="Push Messaging and Notifications Sample">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon-precomposed" href="../images/apple-touch-icon-precomposed.png">
    <!-- Tile icon for Win8 (144x144 + tile color) -->
    <meta name="msapplication-TileImage" content="images/touch/ms-touch-icon-144x144-precomposed.png">
    <meta name="msapplication-TileColor" content="#3372DF">
    <link rel="icon" href="../images/favicon.ico">
    <!-- Include manifest file in the page -->
    <link rel="manifest" href="manifest.json">

<body>
    <h1>Push Messaging &amp; Notifications</h1>
    <p>
        <button class="js-push-button" disabled>
            Enable Push Messages
        </button>
    </p>
    <br />
    <br />
    <h2>cURL Command to Send Push</h2>
    <div class="js-curl-command"></div>
    <script src="config.js"></script>
    <script src="demo.js"></script>
    <script src="main.js"></script>
</body>
</html>

main.js

    'use strict';
var API_KEY = window.GoogleSamples.Config.gcmAPIKey;
var GCM_ENDPOINT = 'https://android.googleapis.com/gcm/send';
var curlCommandDiv = document.querySelector('.js-curl-command');
var isPushEnabled = false;
// This method handles the removal of subscriptionId
// in Chrome 44 by concatenating the subscription Id
// to the subscription endpoint
function endpointWorkaround(pushSubscription) {
    // Make sure we only mess with GCM
    if (pushSubscription.endpoint.indexOf('https://android.googleapis.com/gcm/send') !== 0) {
        return pushSubscription.endpoint;
    }
    var mergedEndpoint = pushSubscription.endpoint;
    // Chrome 42 + 43 will not have the subscriptionId attached
    // to the endpoint.
    if (pushSubscription.subscriptionId &&
      pushSubscription.endpoint.indexOf(pushSubscription.subscriptionId) === -1) {
        // Handle version 42 where you have separate subId and Endpoint
        mergedEndpoint = pushSubscription.endpoint + '/' +
          pushSubscription.subscriptionId;
    }
    return mergedEndpoint;
}
function sendSubscriptionToServer(subscription) {
    // TODO: Send the subscription.endpoint
    // to your server and save it to send a
    // push message at a later date
    //
    // For compatibly of Chrome 43, get the endpoint via
    // endpointWorkaround(subscription)
    var sub = subscription.endpoint;
    var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      //document.getElementById("demo").innerHTML = xhttp.responseText;
    }
  }
  xhttp.open("POST", "myusers.php?id="+sub, true);
  xhttp.send();
    console.log(subscription.endpoint);
    var mergedEndpoint = endpointWorkaround(subscription);
    // This is just for demo purposes / an easy to test by
    // generating the appropriate cURL command
    showCurlCommand(mergedEndpoint);
}
// NOTE: This code is only suitable for GCM endpoints,
// When another browser has a working version, alter
// this to send a PUSH request directly to the endpoint
function showCurlCommand(mergedEndpoint) {
    // The curl command to trigger a push message straight from GCM
    if (mergedEndpoint.indexOf(GCM_ENDPOINT) !== 0) {
        window.Demo.debug.log('This browser isn't currently ' +
          'supported for this demo');
        return;
    }
    var endpointSections = mergedEndpoint.split('/');
    var subscriptionId = endpointSections[endpointSections.length - 1];
    var curlCommand = 'curl --header "Authorization: key=' + API_KEY +
      '" --header Content-Type:"application/json" ' + GCM_ENDPOINT +
      ' -d "{\"registration_ids\":[\"' + subscriptionId + '\"]}"';
    curlCommandDiv.textContent = curlCommand;
}
function unsubscribe() {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;
    curlCommandDiv.textContent = '';
    navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
        // To unsubscribe from push messaging, you need get the
        // subcription object, which you can call unsubscribe() on.
        serviceWorkerRegistration.pushManager.getSubscription().then(
          function (pushSubscription) {
              // Check we have a subscription to unsubscribe
              if (!pushSubscription) {
                  // No subscription object, so set the state
                  // to allow the user to subscribe to push
                  isPushEnabled = false;
                  pushButton.disabled = false;
                  pushButton.textContent = 'Enable Push Messages';
                  return;
              }
              // TODO: Make a request to your server to remove
              // the users data from your data store so you
              // don't attempt to send them push messages anymore
              // We have a subcription, so call unsubscribe on it
              pushSubscription.unsubscribe().then(function (successful) {
                  pushButton.disabled = false;
                  pushButton.textContent = 'Enable Push Messages';
                  isPushEnabled = false;
              }).catch(function (e) {
                  // We failed to unsubscribe, this can lead to
                  // an unusual state, so may be best to remove
                  // the subscription id from your data store and
                  // inform the user that you disabled push
                  window.Demo.debug.log('Unsubscription error: ', e);
                  pushButton.disabled = false;
              });
          }).catch(function (e) {
              window.Demo.debug.log('Error thrown while unsubscribing from ' +
                'push messaging.', e);
          });
    });
}
function subscribe() {
    // Disable the button so it can't be changed while
    // we process the permission request
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;
    navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
        serviceWorkerRegistration.pushManager.subscribe({ userVisibleOnly: true })
          .then(function (subscription) {
              // The subscription was successful
              isPushEnabled = true;
              pushButton.textContent = 'Disable Push Messages';
              pushButton.disabled = false;
              // TODO: Send the subscription subscription.endpoint
              // to your server and save it to send a push message
              // at a later date
              return sendSubscriptionToServer(subscription);
          })
          .catch(function (e) {
              if (Notification.permission === 'denied') {
                  // The user denied the notification permission which
                  // means we failed to subscribe and the user will need
                  // to manually change the notification permission to
                  // subscribe to push messages
                  window.Demo.debug.log('Permission for Notifications was denied');
                  pushButton.disabled = true;
              } else {
                  // A problem occurred with the subscription, this can
                  // often be down to an issue or lack of the gcm_sender_id
                  // and / or gcm_user_visible_only
                  window.Demo.debug.log('Unable to subscribe to push.', e);
                  pushButton.disabled = false;
                  pushButton.textContent = 'Enable Push Messages';
              }
          });
    });
}
// Once the service worker is registered set the initial state
function initialiseState() {
    // Are Notifications supported in the service worker?
    if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
        window.Demo.debug.log('Notifications aren't supported.');
        return;
    }
    // Check the current Notification permission.
    // If its denied, it's a permanent block until the
    // user changes the permission
    if (Notification.permission === 'denied') {
        window.Demo.debug.log('The user has blocked notifications.');
        return;
    }
    // Check if push messaging is supported
    if (!('PushManager' in window)) {
        window.Demo.debug.log('Push messaging isn't supported.');
        return;
    }
    // We need the service worker registration to check for a subscription
    navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
        // Do we already have a push message subscription?
        serviceWorkerRegistration.pushManager.getSubscription()
          .then(function (subscription) {
              // Enable any UI which subscribes / unsubscribes from
              // push messages.
              var pushButton = document.querySelector('.js-push-button');
              pushButton.disabled = false;
              if (!subscription) {
                  // We aren’t subscribed to push, so set UI
                  // to allow the user to enable push
                  return;
              }
              // Keep your server in sync with the latest subscription
              sendSubscriptionToServer(subscription);
              // Set your UI to show they have subscribed for
              // push messages
              pushButton.textContent = 'Disable Push Messages';
              isPushEnabled = true;
          })
          .catch(function (err) {
              window.Demo.debug.log('Error during getSubscription()', err);
          });
    });
}
window.addEventListener('load', function () {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.addEventListener('click', function () {
        if (isPushEnabled) {
            unsubscribe();
        } else {
            subscribe();
        }
    });
    // Check that service workers are supported, if so, progressively
    // enhance and add push messaging support, otherwise continue without it.
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('service-worker.js')
        .then(initialiseState);
    } else {
        window.Demo.debug.log('Service workers aren't supported in this browser.');
    }
});

config.js

window.GoogleSamples = window.GoogleSamples || {};
window.GoogleSamples.Config = window.GoogleSamples.Config || {
    gcmAPIKey: '&lt;Your Public API Key ...&gt;'
};

service-worker.js

'use strict';
self.addEventListener('push', function (event) {
    console.log('Received a push message', event);
    var title = 'Yay a message.';
    var body = 'We have received a push message.';
    var icon = '/images/icon-192x192.png';
    var tag = 'simple-push-demo-notification-tag';
    event.waitUntil(
      self.registration.showNotification(title, {
          body: body,
          icon: icon,
          tag: tag
      })
    );
});

self.addEventListener('notificationclick', function (event) {
    console.log('On notification click: ', event.notification.tag);
    // Android doesn’t close the notification when you click on it
    // See: http://crbug.com/463146
    event.notification.close();
    // This looks to see if the current is already open and
    // focuses if it is
    event.waitUntil(clients.matchAll({
        type: "window"
    }).then(function (clientList) {
        for (var i = 0; i < clientList.length; i++) {
            var client = clientList[i];
            if (client.url == '/' && 'focus' in client)
                return client.focus();
        }
        if (clients.openWindow)
            return clients.openWindow('/');
    }));
});

demo.js

 'use strict';
    function Debug() {
    }
    Debug.prototype.log = function () {
        var paragraphElement = document.createElement('p');
        paragraphElement.textContent = Array.prototype.join.call(arguments, '');
        document.querySelector('.js-log').appendChild(paragraphElement);
    }
    window.addEventListener('load', function () {
        var logDiv = document.createElement('div');
        logDiv.classList.add('js-log');
        var heading = document.createElement('h2');
        heading.textContent = 'Log';
        logDiv.appendChild(heading);
        document.body.appendChild(logDiv);
        window.Demo = window.Demo || {};
        window.Demo.debug = window.Demo.debug || new Debug();
    });

写完这些代码之后还能做什么??我没有使用过gcm,所以发现很难启用,需要帮助。

是的,编写服务器端代码是"真实"用例所必需的。curl命令只是作为功能的一次性测试。

https://github.com/gauntface/simple-push-demo是一个很好的服务器端起点,假设后端是Python App Engine。

一些例子

https://github.com/beverloo/peter.sh/tree/master/tests有非常基本的PHP版本的服务器端代码。你可以忽略所有加密相关的东西,因为只有当你需要发送有效载荷时才需要。

https://github.com/johnmellor/push-api-appengine-demo包含一个python服务器端实现,您可以在https://johnme-gcm.appspot.com/chat/

中尝试。

实际的发送代码非常直接。发送一个JSON请求,如下所示

{
        'registration_ids': registration_ids,
        'collapse_key': "constantString",
}

通过POST消息到https://android.googleapis.com/gcm/send完整的API和一些更多的例子(不是特定于web推送,但仍然有用)在https://developers.google.com/cloud-messaging/

相关内容

  • 没有找到相关文章

最新更新