Notifications API は、システムレベルでページ外部に表示される通知を Web ページやアプリから送ることを可能にします。これにより、アプリケーションがアイドルやバックグラウンドの状態であっても、アプリからユーザに情報を送信できます。この記事では、アプリで API を使用する方法の基礎を見ていきます。
一般的にシステム通知とは、オペレーティングシステムの標準的な通知メカニズムを指します。一般的なデスクトップシステムやモバイルデバイスが、通知を行う方法の実例を思い出しましょう。
当然ながらシステム通知の仕組みはプラットフォームやブラウザによって異なりますが問題はなく、Notifications API はほとんどのシステム通知に対して十分な互換性を持つようになっています。
例
Web Notifications のもっともわかりやすい用途のひとつが、ユーザが別のアプリケーションを使用しているときでも新しいメッセージを受信したら通知が必要な、Web ベースのメールや IRC アプリケーションです。Slack など、実例がたくさんあります。
Web Notifications をどのように使用するかのアイデアを示すため、2 つの実例を掲載します:
- To-do list: IndexedDB を使用してデータをローカルに保存して、タスクの期限が来たときにシステム通知を使用して知らせるシンプルな To-Do リストアプリです。To-do list のコードをダウンロードするか、アプリを実行してみてください。
- Emogotchi: たまごっちのややばかげたパロディであり、Emo を哀れな状態にし続けられなければ、負けになってしまいます。システム通知を使用して、あなたの行動に満足したかや不満をずっと言い続けます。Emogotchi のコードをダウンロードするか、実行してみてください。
.
許可の要求
アプリが通知を送信可能になる前に、ユーザはアプリがそれを行う権利を認めなければなりません。これは、API が Web ページの外部にあるものと対話しようとする際の一般的な要件です。ユーザは少なくとも 1 回はアプリケーションが通知を送ることを認めなければならず、これによりどのアプリやサイトが通知を表示してよいかをユーザが制御できます。
現在の許可状態を確認する
読み取り専用の Notification.permission
プロパティの値を調べると、すでに許可を得ているかを確認できます。このプロパティは、3 種類の値のいずれかを持ちます:
default
- ユーザはまだ許可を求められておらず、通知は表示されません。
granted
- ユーザは以前に通知表示の許可を求められており、許可しました。
denied
- ユーザは、通知の表示を明示的に拒否しました。
許可を得る
通知を表示する許可をまだ得ていない場合は、ユーザへ許可を求めるためにアプリケーションで Notification.requestPermission()
メソッドが必要です。もっともシンプルな形式では Emogotchi のデモで使用しているように、以下のコードを含めます:
Notification.requestPermission();
このメソッドは任意でコールバック関数を指定でき、この関数は通知の表示を許可するかの要求に答えたときに呼び出されます (以下のサンプルで 2 番目の else ... if
ブロックを参照)。一般的に通知を表示する許可は、アプリを最初に初期化するときでインスタンス化を行う前に要求します。完全な形にしたい場合は、以下のような構成を使用するとよいでしょう (To-do List Notifications をご覧ください):
function notifyMe() { // ブラウザが通知をサポートしているか確認する if (!("Notification" in window)) { alert("このブラウザはシステム通知をサポートしていません"); } // すでに通知の許可を得ているか確認する else if (Notification.permission === "granted") { // 許可を得ている場合は、通知を作成する var notification = new Notification("Hi there!"); } // 許可を得ていない場合は、ユーザに許可を求めなければならない else if (Notification.permission !== 'denied') { Notification.requestPermission(function (permission) { // ユーザが許可した場合は、通知を作成する if (permission === "granted") { var notification = new Notification("Hi there!"); } }); } // 最後に、ユーザが通知を拒否した場合は、これ以上ユーザに // 迷惑をかけてはいけないことを尊重すべきです。 }
注記: バージョン 37 より前の Chrome は、load
イベントハンドラ内で Notification.requestPermission()
を呼び出してはいけませんでした (issue 274284 をご覧ください)。
Firefox OS マニフェストでの許可設定
Notifications API は privileged や certified ではありませんが、Firefox OS アプリに manifest.webapp
ファイルを含める際に項目を含めてください:
"permissions": { "desktop-notification": { "description": "Needed for creating system notifications." } }, "messages": [{"notification": "path/to/your/index.html"}]
注記: アプリケーションをインストールするとき、明示的に許可を求める必要はありませんが、通知を行うためには permissions および messages の項目が必要です。
通知を作成する
通知は簡単に作成でき、Notification
コンストラクタを使用するだけです。このコンストラクタは通知で表示するタイトルや、アイコン
あるいはテキスト本文
といったオプションを受け取ると想定します。
例えば Emogotchi では、通知が必要になった際に呼び出す関数が 2 つあります。ひとつは通知を設定したいかに応じて呼び出すもの、もうひとつはランダムな内容を含む通知です:
function spawnNotification(theBody,theIcon,theTitle) { var options = { body: theBody, icon: theIcon } var n = new Notification(theTitle,options); setTimeout(n.close.bind(n), 5000); } function randomNotification() { var randomQuote = quoteChooser(); var options = { body: randomQuote, icon: 'img/sad_head.png', } var n = new Notification('Emogotchi says',options); setTimeout(n.close.bind(n), 5000); }
通知を閉じる
Firefox および Safari は、少し (4 秒程度) 経過したら自動的に通知を閉じます。またこれは、オペレーティングシステムレベルで行われます。一方 Chrome など、動作が異なるブラウザがあります。すべてのブラウザで確実に通知を閉じるには 4 秒後に通知を閉じるため、前出の関数の末尾に Notification.close
関数を収めた setTimeout()
関数を置きます。close()
を通知に関連付けて呼び出すために bind()
を使用していることに注意してください。
setTimeout(n.close.bind(n), 5000);
注記: "close" イベントを受け取るとき、ユーザが通知を閉じたことは保証されません。これは仕様書に準拠しており、以下のように記載されています: "When a notification is closed, either by the underlying notifications platform or by the user, the close steps for it must be run."
Notification イベント
Notifications API の仕様では、Notification
のインスタンスで発生するイベントを 2 つ定義しています:
これらのイベントは、onclick
および onerror
ハンドラを使用して追跡できます。Notification
は EventTarget
も継承していますので、addEventListener()
メソッドも使用できます。
仕様書で定義されていたイベントはもう 2 つありますが、最近削除されました。しばらくの間ブラウザで動作しますが、廃止扱いされて使用できなくなるでしょう:
既存の通知を置き換える
ユーザが短期間に多くの通知を受け取ることは、通常望ましくありません。例えばメッセンジャーアプリがメッセージを受け取るたびに通知を行って、それが大量になったらいかがでしょうか? 大量の通知によるスパム状態を避けるため、準備中の通知キューを変更して 1 つ以上の未表示通知を新た通知で置き換えることができます。
これを行うために、任意の新たな通知にタグを付加できます。すでに同じタグがついている通知がまだ表示されていない場合は、新しい通知が以前の通知を置き換えます。同じタグがついている通知がすでに表示されている場合は、前の通知を閉じて新しい通知を表示します。
タグの例
以下の基本的な HTML を想定します:
<button>Notify me!</button>
以下の方法で、複数の通知を扱うことが可能です:
window.addEventListener('load', function () { // 始めに、通知の許可を得ているかを確認しましょう // 得ていなければ、尋ねましょう if (window.Notification && Notification.permission !== "granted") { Notification.requestPermission(function (status) { if (Notification.permission !== status) { Notification.permission = status; } }); } var button = document.getElementsByTagName('button')[0]; button.addEventListener('click', function () { // 通知されることにユーザが同意している場合 // 10 個の通知を送信してみましょう if (window.Notification && Notification.permission === "granted") { var i = 0; // 一部のブラウザ (Firefox を含む) は一定の期間内に大量の通知を行うとブロックするため、interval を使用します。 var interval = window.setInterval(function () { // タグのおかげで、私たちは "Hi!9" の通知だけを見るでしょう var n = new Notification("Hi! " + i, {tag: 'soManyNotification'}); if (i++ == 9) { window.clearInterval(interval); } }, 200); } // 通知を受けたいか否かをユーザが告げていない場合 // 注記: Chrome のために permission プロパティが設定されているかの確信が // 持てないため、値 "default" を確認するのは安全ではありません。 else if (window.Notification && Notification.permission !== "denied") { Notification.requestPermission(function (status) { if (Notification.permission !== status) { Notification.permission = status; } // ユーザが認めている場合 if (status === "granted") { var i = 0; // 一部のブラウザ (Firefox を含む) は一定の期間内に大量の通知を行うとブロックするため、interval を使用します。 var interval = window.setInterval(function () { // タグのおかげで、私たちは "Hi!9" の通知だけを見るでしょう var n = new Notification("Hi! " + i, {tag: 'soManyNotification'}); if (i++ == 9) { window.clearInterval(interval); } }, 200); } // 認めていなければ、通常型の alert にフォールバックします else { alert("Hi!"); } }); } // ユーザが通知を拒否している場合 else { // 通常型の alert にフォールバックできます alert("Hi!"); } }); });
結果は以下のとおりです:
アプリの通知をクリックしたことの通知を受ける
アプリが生成した通知をユーザがクリックしたとき、アプリ側では状況に応じて 2 つの方法でクリックイベントの通知を受け取ることができます:
- 通知を作成してからユーザが通知をクリックするまでの間に、アプリが閉じられたりバックグラウンドに移されたりしていない場合は、click イベントを使用できます。
- それ以外の場合は、システムメッセージを使用します。
これらの扱い方の例については、こちらのコードスニペットをご覧ください。
仕様
仕様書 | 策定状況 | コメント |
---|---|---|
Notifications API | 勧告 | Living standard |
ブラウザ実装状況
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 5webkit[1] 22 |
4.0 moz[2] 22 |
未サポート | 25 | 6[3] |
icon |
5webkit[1] 22 |
4.0 moz[2] 22 |
未サポート | 25 | 未サポート |
Available in workers | ? | 41.0 (41.0) | ? | ? | ? |
silent |
43.0 | 未サポート | 未サポート | 未サポート | 未サポート |
noscreen , renotify , sound , sticky |
未サポート | 未サポート | 未サポート | 未サポート | 未サポート |
Feature | Android | Android Webview | Firefox Mobile (Gecko) | Firefox OS | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|---|
Basic support | ? |
(有) |
4.0moz[2] 22 |
1.0.1moz[2] 1.2 |
未サポート | ? | 未サポート |
(有) |
icon |
? | (有) | 4.0moz[2] 22 |
1.0.1moz[2] 1.2 |
未サポート | ? | 未サポート | (有) |
Available in workers | ? | ? | 41.0 (41.0) | ? | ? | ? | ? | ? |
silent |
未サポート | 43.0 | 未サポート | 未サポート | 未サポート | 未サポート | 未サポート | 43.0 |
noscreen , renotify , sound , sticky |
未サポート | 未サポート | 未サポート | 未サポート | 未サポート | 未サポート | 未サポート | 未サポート |
[1] Chrome 22以前では、次の古いプレフィックス付きバージョンの仕様がサポートされており、新しい通知のインスタンスにはnavigator.webkitNotifications
オブジェクトを使用します。
Chrome 32以前では、Notification.permission
はサポートされていませんでした。
Chrome 42以前では、サービスワーカーの追加はサポートされていませんでした。
Chrome 49以降では、シークレットモードで通知はサポートされていません。
[2] Firefox 22 (Firefox OS <1.2)以前では、navigator.mozNotification
オブジェクトを通じてcreateNotificationメソッドにより新しい通知を実行する必要があります。
Firefox 22 (Firefox OS <1.2)以前では、showメソッドを呼び出すと通知が表示され、 click
とclose
イベントのみがサポートされています。
Nick Desaulniersは、Notification shimにおいて新旧両方の実装をカバーしています。
One particular Firefox OS issue is that you can pass a path to an icon to use in the notification, but if the app is packaged you cannot use a relative path like /my_icon.png
. You also can't use window.location.origin + "/my_icon.png"
because window.location.origin
is null in packaged apps. The manifest origin field fixes this, but it is only available in Firefox OS 1.1+. A potential solution for supporting Firefox OS <1.1 is to pass an absolute URL to an externally hosted version of the icon. This is less than ideal as the notification is displayed immediately without the icon, then the icon is fetched, but it works on all versions of Firefox OS.
When using notifications in a Firefox OS app, be sure to add the desktop-notification
permission in your manifest file. Notifications can be used at any permission level, hosted or above: "permissions": { "desktop-notification": {} }
[3] Safari started to support notification with Safari 6, but only on Mac OSX 10.8+ (Mountain Lion).