[PWA]プッシュ通知を実現するPushAPIとNotificationAPI


Webアプリにおけるプッシュ通知

  • PWAを代表する機能としてプッシュ通知があげられることがよくあると思います(iPhone/Safariだとまだ使えないんですがね)
  • Webアプリにおけるプッシュ通知はPushAPINotificationAPIというの2つの仕組みからなっています


PushAPI

  • PushAPIはサーバからの通知を受け取ることができるAPIです

NotificationAPI

  • NotificationAPIはユーザに対して通知を送ることができるAPIです

一連の流れ

  • Webアプリにおけるプッシュ通知送信までの一連の流れは、PushAPIがサーバからの通知を受け取り、NotificationAPIを呼び出してユーザに通知を送ります

  • それぞれの使い方を整理しようと思いましたが思いの外大変だったので今回はNotificationAPIを紹介します

NotificationAPIの使い方

  • NotificationAPIはユーザに通知を送るAPIでした
  • 通知を送るためには事前に許可を得る必要があります
    • 見た瞬間に拒否を押してしまうあれですね・・・(許可を得るタイミングはよく考えて実装しましょう!)

  • というわけで許可をとるフェーズ通知を送るフェーズの2つに分けて説明していきます

許可を取るフェーズ

  • 通知の許可を得るためにはNotification.requestPermission()を実行することでユーザに尋ねることができます
  • requestPermission()はPromiseを返し、ユーザが 許可 or ブロック を選択するとresolveされて結果を取得できます
    • 許可ならgranted、ブロックならdenidedという値を取得できます
  • 以下のコードで試すことができます
<button id="confirm">通知の許可を取得する</button>
<script>
  document.getElementById('confirm').addEventListener('click', () => {
    Notification.requestPermission().then(permission => {
      alert(permission); // granted or denied
    });
  });
</script>
  • 現在の許可状態を確認することができるNotification.permissionというものもあります
  • 許可状態はdefault(未回答)、granted(許可済み)、denied(ブロック)の3つのいずれかが返ります
const permission = Notification.permission;
console.log(permission); // default, granted or denied

通知を送るフェーズ

  • 許可を得ると通知を送信できるようになります
  • 以前はnew Notification('通知の内容')でも送信できましたが手元のAndroidではエラーとなり、ちょっとググってみたところこのやり方は非推奨で以下で紹介するServiveWorkerから送るやり方が推奨されるとのことです
  • メッセージの送信はServiveWorker上でself.registration.showNotification('通知の内容')といった感じで送信できます
  • 以下のコードは動作確認しやすいようにブラウザからServiceWorkerにpostMessageでメッセージを送り、ServiceWorkerはそれを受け取ってプッシュ通知を送っています
index.html
<button id="send">通知を送信する</button>
<script>
  // ServiceWorkerの登録
  window.addEventListener('load', () => {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker
        .register('sw.js')
        .then(registration => console.log('registered', registration))
        .catch(error => console.log('error', error));
    }
  });

  // 通知の送信
  document.getElementById('send').addEventListener('click', () => {
    if (Notification.permission === 'granted') {
      navigator.serviceWorker.ready.then(registration => {
        registration.active.postMessage('hello!!!');
      });
    }
  });
</script>
sw.js
self.addEventListener('message', function (event) {
  self.registration.showNotification(event.data);
});

サンプル

まとめ

  • 調べながらだと時間かかりましたが自前でも十分実装できるレベル感ですね
  • PushAPIの部分も時間があればまた調べたいと思います