プッシュ通知を聞いたら思い出すのがネイティブAPPでしょう。でも、ServiceWorkerを通じ、WebAPPでもプッシュ通知ができるとご存知ですか。
ServiceWorkerはPWA(Progressive Web Apps)の不可欠なツールとなります。ServiceWorkerを使うことで、バックエンドでデータの同期、キャッシュなど、WebAPPをオフライン状態でも動くネイティブAPPのようなユーザ体験を提供するができます。
さらに、ネイティブAPPと同じように、プッシュ通知もできます。しかし、Webプッシュ通知はFCM(Firebase Cloud Messaging)みたいな送信用のエンドポイントが必要となります。すなわち、Webプッシュ通知にはサーバーへの通信
、オンライン
が必要です。
しかし、スケジュール通りに通知するのがオンライン、オフラインと関わらず、全ての環境に使えることが望ましいです。例えば、「お薬の時間です」
や「ベランダの野菜に肥料の日です」
など、インタネットの環境がなくても通知するのが重要でしょう。
それを実現するために、Webプッシュ通知のスケジュール機能が現れました。現時点(2020.05.25)まだ試験中なんですが、近くの未来にリリースされるでしょう。
今日はWebプッシュ通知のスケジューラーを実装してみましょう*。
※デスクトップのChromeのみ動作確認しています。
準備
-
Chromeの
#enable-experimental-web-platform-features
を有効へchrome://flags/を開いて、#enable-experimental-web-platform-featuresを検索して有効にしてください。
。
-
ServiceWorker用の
https
環境の構築Macなら簡単ですが、Windowsならちょっと煩雑となります。Windowsなら5分でWindowsにhttps://localhost:8080を立ち上げるを読んでみてください。
フォルダ構成
/project
├── index.html
├── app.js
├── sw.js
ServiceWorkerを登録
ServiceWorkerの利用可能かチェックします。
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register('./sw.js');
}
ServiceWorkerをインストール
self.addEventListener("install", () => {
console.log("SW installed!");
});
いきなりプッシュ通知のスケジューラーの実装
/**
* todoTime: UNIXエポック*から経過したミリ秒
*/
async function registerTodo({todoName, todoTime, title = "Todo"}) {
const reg = await navigator.serviceWorker.getRegistration();
Notification.requestPermission().then((permission) => {
if (permission !== "granted") {
// プッシュ通知許可されない場合エラー
alert("You have to allow push notifications!");
return;
}
// プッシュ通知の登録
reg.showNotification(title, {
tag: todoTime,
body: todoName,
showTrigger: new TimestampTrigger(todoTime),
data: {
url: window.location.href,
},
});
});
}
わかりやすいでしょう。キーポイントはTimestampTrigger
です。プッシュ通知の希望時刻を登録すれば、その時刻で通知が来ます。
過ぎた時刻を登録すると、プッシュ通知が待たずにすぐ表示されます。
プッシュ通知が来た時のスクリーンショットはこちらです。
プッシュ通知押下時の処理
下記の機能を実装すれば親切でしょう。
- プッシュ通知がクリックされるとき、1つ目のタブへfocusし、現在のスケジュールを表示させる
- WebAPPが閉じられた場合、Chromeに新らしいタブで自動開く
self.addEventListener("notificationclick", (event) => {
event.waitUntil(
self.clients.matchAll().then((clients) => {
if (clients.length === 0) {
// WebAppが存在しない場合、新しいタブへ
self.clients.openWindow("/");
} else {
// 複数タブの場合、1つ目のタブへfocus
clients[0].focus();
}
})
);
});
テスト
<button type="button" class="btn btn-primary" onclick="addTodoWithPushNotification()">Add Todo</button>
function addTodoWithPushNotification() {
registerTodo("It's time to eat your pills!", new Date().getTime() + 5000, "Doctor's hint");
}
ボタンをクリックすると、5秒後
通知が来るはずです。タイトルはDoctor’s hint、内容はIt’s time to eat your pillsとなります。
完了
実装は以上となります。意外に簡単でしょう。興味があれば、サンプルプロジェクトで試してみましょう。
ソースコード:https://github.com/thundermiracle/try-scheduled-push
サンプルページ:https://thundermiracle.github.io/try-scheduled-push/