使用 Web Notifications

這是一個實驗中的功能
此功能在某些瀏覽器尚在開發中,請參考兼容表格以得到不同瀏覽器用的前輟。

摘要

Web Notifications API 可將通知傳送至頁面以外的系統層級並顯示通知。因此即使 Web Apps 處於閒置狀態,亦可傳送資訊予使用者。絕佳範例之一,就是在使用其他 Apps 時,Web Mail App 同樣可通知使用者已接收到新郵件。

要求權限

網頁內容

在 Apps 傳送通知之前,使用者必須先許可 Apps 的動作。只要 APIs 嘗試予網頁之外的東西互動,均必須先獲得使用者的授權。如此可避免濫發通知而影響使用經驗。

透過 Notification.permission 唯讀屬性,要傳送通知的 Apps 將檢查目前的授權狀態。此屬性共有 3 組參數:

  • default:使用者尚未給予任何權限 (因此不會顯示任何通知)
  • granted:使用者允許接收到 Apps 的通知
  • denied:使用者拒絕接收 Apps 的通知

注意:Chrome 與 Safari 尚未建構 permission 屬性。

若使用者尚未給予權限,則 Apps 必須透過 Notification.requestPermission() 函式讓使用者選擇,接著由此函式接收 1 組回呼 (Callback) 函式作為參數;而該回呼函式則提供使用者是否授權的資訊。

以下為啟動 Apps 時要求權限的常用範例:

window.addEventListener('load', function () {
  Notification.requestPermission(function (status) {
    // This allows to use Notification.permission with Chrome/Safari
    if (Notification.permission !== status) {
      Notification.permission = status;
    }
  });
});

注意:Chrome 不允許於載入事件中呼叫 Notification.requestPermission() (參閱 issue 274284)。

已安裝的 Apps

在安裝 Apps 之後,若於 Apps 的 manifest 檔案中直接添加權限,即可省去再次向使用者要求權限的動作。

permissions: {
  "desktop-notification": {
    "description: "Allows to display notifications on the user's desktop.
  }
}

建立通知

透過 Notification 建構子 (Constructor) 即可建立通知。此建構子包含 1 組標題,可於通知內顯示;另有如 icon 或文字 body數個選項,可強化通知的內容。

在建立實體 (Instantiated) 之後,就會儘快顯示通知。若要追蹤通知的目前狀態,必須在 Notification 的實體階層觸發 4 個事件:

  • show:對使用者顯示通知之後,隨即觸發
  • click:使用者點擊通知之後,隨即觸發
  • close:關閉通知之後,隨即觸發
  • error:通知發生任何錯誤 (大多數是因為某種情況而未顯示通知),隨即觸發

而透過 onshowonclickonclose,或 onerror 等事件處理器 (Event handler),即可追蹤這些事件。由於 Notification 是繼承 EventTarget 而來,因此亦可使用 addEventListener() 函式。

注意:Firefox 與 Safari 並未遵守 close 事件的規格。此規格雖然規定「僅限使用者能關閉通知」,但 Firefox 與 Safari 卻可於數分鐘後自動關閉通知。因此不一定是由使用者關閉通知。

此規格並明確規定「應透過 Notification.close() 函式,於應用程式層級完成自動關閉通知」。範例程式碼如下:

var n = new Notification("Hi!");
n.onshow = function () {
  setTimeout(n.close, 5000);
}

簡易範例

先假設下列基本 HTML:

<button>Notify me!</button>

則能以這種方法處理通知:

window.addEventListener('load', function () {
  // At first, let's check if we have permission for notification
  // If not, let's ask for it
  if (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 () {
    // If the user agreed to get notified
    if (Notification && Notification.permission === "granted") {
      var n = new Notification("Hi!");
    }
    // If the user hasn't told if he wants to be notified or not
    // Note: because of Chrome, we are not sure the permission property
    // is set, therefore it's unsafe to check for the "default" value.
    else if (Notification && Notification.permission !== "denied") {
      Notification.requestPermission(function (status) {
        if (Notification.permission !== status) {
          Notification.permission = status;
        }
        // If the user said okay
        if (status === "granted") {
          var n = new Notification("Hi!");
        }
        // Otherwise, we can fallback to a regular modal alert
        else {
          alert(Hi!");
        }
      });
    }
    // If the user refuses to get notified
    else {
      // We can fallback to a regular modal alert
      alert(Hi!");
    }
  });
});

現場測試結果

若無法顯示,可至本文右上角「Language」切換回英文原文觀看。

處理多筆通知

某些情況下 (如某個即時訊息 App 持續通知每一筆進來的訊息),使用者可能會接收大量的通知。為了避免太多非必要訊息擠爆使用者的桌面,則應該讓等待中的通知進入佇列。

將標籤添加至任何新的通知,即可達到佇列效果。若通知擁有相同的標籤且尚未顯示,則新通知就會取代先前的通知;反之,若已顯示了相同標籤的通知,就會關閉先前的通知而顯示新通知。

標籤範例

先假設下列基本 HTML:

<button>Notify me!</button>

則能以下列方式處理多筆通知:

window.addEventListener('load', function () {
  // At first, let's check if we have permission for notification
  // If not, let's ask for it
  if (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 () {
    // If the user agreed to get notified
    // Let's try to send ten notifications
    if (Notification && Notification.permission === "granted") {
      for (var i = 0; i < 10; i++) {
        // Thanks to the tag, we should only see the "Hi! 10" notification
        var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
      }
    }
    // If the user hasn't told if he wants to be notified or not
    // Note: because of Chrome, we are not sure the permission property
    // is set, therefore it's unsafe to check for the "default" value.
    else if (Notification && Notification.permission !== "denied") {
      Notification.requestPermission(function (status) {
        if (Notification.permission !== status) {
          Notification.permission = status;
        }
        // If the user said okay
        if (status === "granted") {
          for (var i = 0; i < 10; i++) {
            // Thanks to the tag, we should only see the "Hi! 10" notification
            var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
          }
        }
        // Otherwise, we can fallback to a regular modal alert
        else {
          alert(Hi!");
        }
      });
    }
    // If the user refuses to get notified
    else {
      // We can fallback to a regular modal alert
      alert(Hi!");
    }
  });
});

現場測試結果

若無法顯示,可至本文右上角「Language」切換回英文原文觀看。

規格

Specification Status Comment
Web Notifications Working Draft Initial specification.

瀏覽器相容性

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 5 webkit (see notes)
22
4.0 moz (see notes)
22
Not supported ? 6 (see notes)
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support ? 4.0 moz (see notes)
22
Not supported ? ?

Gecko notes

  • Prior to Firefox 22 (Firefox OS <1.2), the instantiation of a new notification must be done with the navigator.mozNotification object through its createNotification method.
  • Prior to Firefox 22 (Firefox OS <1.2), the Notification was displayed when calling the show method and was supporting the click and close events only.
  • Nick Desaulniers has written a Notification shim to cover both newer and older implementations.
  • 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 navigator.location.origin + "/my_icon.png" because navigator.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 with the icon missing, then the icon is fetched, but it works on all versions of Firefox OS.

Chrome notes

Safari notes

  • Safari started supporting notification with Safari 6 but only on Mac OSX 10.8+ (Mountain Lion).

另可參閱

文件標籤與貢獻者

 此頁面的貢獻者: MashKao
 最近更新: MashKao,