PWAの基礎知識(その8)「Push API/Chrome編」
PWAを構成する技術要素の一つにプッシュ通知があります。Push APIがそうで、該当URLを開いていなくても通知を受けられる仕組みです。
Push APIには幾つかの実装方法がありますが、今回はFCM/GCMを使ったGoogle Chrome向けの実装を紹介します。
Firebaseでプロジェクトを作成する
FCMを使うので、まず最初にFirebaseでプロジェクトを作成します。
作成した後、ウェブアプリにFirebaseを追加を選択します。
そして表示されるモーダルの中に messagingSenderId
という項目があります。これを覚えておきます。
さらにプロジェクトの設定を選び、クラウドメッセージングを選びます。
その中に表示される、サーバーキーも覚えておきます。
必要な技術
Push APIを使う際に必要なのはService Workerになります。
manifest.jsonの作成
manifest.jsonを作成します。内容は例えば以下のようになります。 YOUR_SENDER_ID
となっているところは先ほどの messagingSenderId
の値になります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "Push Notification Demo", | |
"short_name": "Push Notification Demo", | |
"gcm_sender_id": "YOUR_SENDER_ID" | |
} |
serviceworker.js の作成
Service Worker用のJavaScriptファイルを作成します。 serviceworker.js
とします。今回は簡単な内容にしています。最低限必要なのは install と push イベントになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.addEventListener('install', () => { | |
console.log('ServiceWorker がインストールされました'); | |
}); | |
self.addEventListener('push', ev => { | |
self.registration.showNotification('メッセージが届きました', { | |
body: '新しいメッセージです' | |
}); | |
}); |
HTMLの記述
HTMLではmanifest.jsonを読み込みます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="manifest" href="manifest.json"> |
JavaScriptの記述
初期化
まずPush通知が使えるかどうか、さらに購読中かどうかを判別します。以下のようなコードで順番に確認できます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function onLoad() { | |
if (!('serviceWorker' in navigator)) { | |
// Service Worker非対応 | |
} | |
navigator.serviceWorker.register('./serviceworker.js') | |
.then(() => { | |
if (!('showNotification' in ServiceWorkerRegistration.prototype)) { | |
// プッシュ通知がサポートされていない場合 | |
return; | |
} | |
if (Notification.permission === 'denied') { | |
// プッシュ通知を拒否された場合 | |
return; | |
} | |
if (!('PushManager' in window)) { | |
// PushManagerが存在しない場合 | |
return; | |
} | |
return navigator.serviceWorker.ready; | |
}) | |
.then(serviceWorkerRegistration => { | |
return serviceWorkerRegistration.pushManager.getSubscription(); | |
}) | |
.then(subscription => { | |
if (!subscription) { | |
// 未購読 | |
} else { | |
// すでに購読中 | |
} | |
}) | |
} |
購読処理
次に購読処理を書きます。これは何かのボタンを押したタイミングなどで実行すれば良いでしょう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const SubscribePushNotification = () => { | |
navigator.serviceWorker.ready | |
.then(serviceWorkerRegistration => { | |
const subscribe = serviceWorkerRegistration | |
.pushManager | |
.subscribe({ | |
userVisibleOnly: true | |
}); | |
return subscribe; | |
}) | |
.then(subscription => { | |
// 購読開始 | |
}) | |
} |
プッシュ通知の送り方
上記のコードで取得できる subscription
には以下のような内容が入っています。
- endpoint
- expirationTime
- options
- options.applicationServerKey
- options.userVisibleOnly
今回のようなFCMから送信する場合に必要なのは endpoint になります。例えば以下のような値です。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://android.googleapis.com/gcm/send/eF7Jh_81aPc:APA9…lOUg |
そして、この対象に対してプッシュ通知を送るには以下のようなコマンドを実行します。 YOUR_API_KEY
となっているのは Firebase で取得したサーバキーになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
curl –header "Authorization: key=YOUR_API_KEY" \ | |
–header Content-Type:"application/json" \ | |
https://android.googleapis.com/gcm/send \ | |
-d "{\"registration_ids\":[\"eF7Jh_81aPc:APA9…lOUg\"]}" |
registration_idsのところに配列でendpointとして取得したトークンを指定すればOKです。
受信する
プッシュ通知を受信すると通知バナーが表示されます。このメッセージは Service Worker側で固定していますが、サーバにfetchで問い合わせてデータ取得することも可能です。登録IDが必要な場合は、以下のコードをService Worker内で実行します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.registration.pushManager.getSubscription().then(subscription => { | |
console.log(subscription.endpoint); // 登録IDが返ってきます | |
}, err => console.log(err)); |
注意点
Push APIはタブを閉じていても(そのURLがアクティブでなくとも)表示されます。ただしGoogle Chromeを終了していたら届きませんので注意してください。Webブラウザを再開すると通知が表示されます。この方式の場合、表示させるメッセージをプッシュ通知側から送ることはできません。データが送れるのは VAPID という方式を使った場合になります。
この方法はGoogle Chrome独自の方式になります。手軽に実装できますが、FirefoxやEdgeなどでは使えませんのでご注意ください。
今回の方式の場合、サーバ側の用意は殆どいりません。取得した登録IDをサーバ側に入れておくだけで大丈夫です。保存する際に任意のユーザIDと結びつけておくことで、プッシュ通知で表示する内容をカスタマイズできるでしょう。
コメントは受け付けていません。