推送訊息可讓您以簡單又有效的方式,再次與使用者進行互動。在這個程式碼研究室中,您將瞭解如何在網路應用程式中新增推播通知。
您將會瞭解的內容
- 如何訂閱及取消訂閱使用者的簡訊
- 如何處理收到的訊息
- 如何顯示通知
- 如何回應通知點擊次數
軟硬體需求
- Chrome 52 以上版本
- Chrome 網路伺服器或您自己的網路伺服器
- 文字編輯器
- HTML、CSS、JavaScript 和 Chrome 開發人員工具的基本知識
- 範例程式碼 (請參閱「進行設定」)。
下載範例程式碼
您可以透過兩種方式,取得這個程式碼研究室的範例程式碼:
- 複製 Git 存放區:
git clone https://github.com/GoogleChrome/push-notifications.git
- 下載 ZIP 檔案:
如果您以 ZIP 檔案格式下載來源檔案,則解壓縮後,系統會提供一個根資料夾 push-notifications-master
。
安裝並驗證網路伺服器
儘管您可以免費使用自己的網路伺服器,但這個程式碼研究室是專為 Chrome 網路應用程式的 Chrome 應用程式所設計。如果您尚未安裝這個應用程式,可以前往 Chrome 線上應用程式商店下載:
安裝 Chrome 網路應用程式 Chrome 版應用程式後,請按一下書籤列的 [應用程式] 捷徑:
在「Apps」視窗中,按一下「Web Server」圖示:
接下來會出現這個對話方塊,供您設定本機網路伺服器:
按一下 [選擇資料夾] 按鈕,然後在您下載的 push-notifications
資料夾中選取 app
資料夾。如此一來,您就可以透過對話方塊顯示的「網路伺服器網址」部分顯示的網址,
在「選項」之下,勾選 [自動顯示 index.html] 旁邊的方塊,如下所示:
然後將 [網路伺服器:STARTED] 開關往左移,接著往右滑動,即可停止伺服器並重新啟動。
按一下 [網路伺服器網址] 即可在網路瀏覽器中造訪您的網站。你應該看到如下所示的頁面:不過你的版本可能會顯示 127.0.0.1:8887 這個位址:
一律更新服務工作站
在開發期間,請確保服務業者隨時保持在最新狀態,並且掌握最新的變更。
如要在 Chrome 中進行設定,請按照下列步驟操作:
- 前往「Push Codelab」分頁。
- 開啟開發人員工具:Windows 和 Linux 系統為 Ctrl-Shift-I 鍵,macOS 則為 Cmd-Option-I 鍵。
- 選擇 [Application] (應用程式) 面板,然後按一下 [Service Workers] (服務工作站) 分頁標籤,然後勾選 [重新載入時更新] 核取方塊。勾選這個核取方塊後,系統就會在每次網頁載入時強制更新 Service Worker。
請注意,您的 app
目錄中有一個名為「sw.js
」的空白檔案。這個檔案將是您的服務業者。現在,它可以保持空白。您稍後就能在其中新增程式碼。
首先,您必須將這個檔案註冊為 Service Worker。
您的 app/index.html
頁面載入了 scripts/main.js
。您會在這個 JavaScript 檔案中註冊 Service Worker。
將下列程式碼加進 scripts/main.js
:
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push are supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
}
瀏覽器會檢查瀏覽器是否支援服務工作人員和推送訊息。如果支援的話,程式碼會註冊您的 sw.js
檔案。
實戰演練
如要重新整理變更,請在瀏覽器中重新整理 [Push Codelab] 分頁。
檢查 Chrome 開發人員工具中的主控台是否出現 Service Worker is registered message
,如下所示:
取得應用程式伺服器金鑰
如要使用這個程式碼研究室,您必須產生應用程式伺服器金鑰。您可以在隨附網站上執行此動作:web-push-codelab.glitch.me
您可以在這裡產生公開和私密金鑰組。
將公開金鑰複製到 scripts/main.js
,取代 <Your Public Key>
值:
const applicationServerPublicKey = '<Your Public Key>';
重要:請絕對不要將私密金鑰放在網頁應用程式中!
目前,網路應用程式的 [啟用] 按鈕已停用,且無法點選。這是因為根據預設,瀏覽器會停用推送按鈕,而您知道瀏覽器是否支援推送訊息功能。此外,您也可以查看使用者目前是否訂閱訊息。
您必須在 scripts/main.js
中建立兩個函式:
initializeUI
:查看使用者是否目前已訂閱updateBtn
:即可啟用按鈕,並根據使用者是否訂閱而變更文字
在 main.js
中加入 initializeUI
函式,如下所示:
function initializeUI() {
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
新方法使用前一步驟中的 swRegistration
,從中取得 pushManager
屬性,然後呼叫 getSubscription()
。
pushManager
。「getSubscription()
」會傳回一個承諾使用現有訂閱項目來解決相關問題。否則,會傳回 null
。您可以在此確認使用者是否已訂閱、設定 isSubscribed
的值,然後呼叫 updateBtn()
以更新按鈕。
將 updateBtn()
函式新增至 main.js
:
function updateBtn() {
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
這項功能會啟用按鈕,並根據使用者是否訂閱而變更按鈕文字。
最後,系統會在您的服務工作人員在 main.js
註冊時呼叫 initializeUI()
:
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
initializeUI();
})
實戰演練
重新整理「Push Codelab」分頁。系統應該已經啟用 [Enable Push Messaging] (啟用推送訊息) 按鈕 (您可以點選該按鈕),您應該會在主控台中看到 User is NOT subscribed
。
在這個程式碼研究室的其餘部分,您應該會在訂閱或取消訂閱時,變更按鈕文字。
目前系統還無法啟用推播訊息按鈕。我們來修正問題。
在 initializeUI()
函式中,為您的按鈕新增點擊事件監聽器:
function initializeUI() {
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
// TODO: Unsubscribe user
} else {
subscribeUser();
}
});
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
updateSubscriptionOnServer(subscription);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
使用者點選按鈕後,您只是停用了該按鈕,確保使用者無法再次點擊按鈕,因為訂閱推送訊息可能需要一些時間。
然後,如果使用者目前並未訂閱,您就會呼叫 subscribeUser()
。若要這麼做,您需將下列程式碼貼到 scripts/main.js
中:
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(error) {
console.error('Failed to subscribe the user: ', error);
updateBtn();
});
}
讓我們逐步瞭解這個程式碼的作用,以及它如何訂閱使用者的推送訊息。
首先,您會取得應用程式伺服器的公開金鑰 (Base64 URL 安全編碼),並將其轉換為 UInt8Array
,因為這是 subscribe()
呼叫的預期輸入內容。urlB64ToUint8Array()
函式位於 scripts/main.js
頂端。
轉換這個值後,您可以在服務工作站的 pushManager
上呼叫 subscribe()
方法,傳入應用程式伺服器的公開金鑰和 userVisibleOnly: true
值。
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
userVisibleOnly
參數可確保您在傳送推送訊息時一律顯示通知。目前,這是必要值,且必須是 true。
呼叫 subscribe()
會傳回承諾,而該步驟將執行,步驟如下:
- 使用者已授予顯示通知的權限。
- 瀏覽器已向網路服務傳送網路要求,以便取得產生
PushSubscription
所需的資料。
如果成功,PushSubscription
將透過 subscribe()
解決。如果使用者未授予權限,或者在使用者訂閱時發生問題,承諾拒絕要求就會遭到拒絕。這樣即可在程式碼研究室中取得下列承諾使用鏈:
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
updateBtn();
});
您可以藉此取得約期授權,並將使用者視為已訂閱,或是發生錯誤並記錄控制台。在這兩種情況下,您都會呼叫 updateBtn()
來確保按鈕已重新啟用,且包含適當的文字。
在實際應用程式中,updateSubscriptionOnServer()
函式可讓您將訂閱資料傳送至後端,但如果是程式碼研究室,您只要直接在 UI 中顯示訂閱即可。將下列函式新增至 scripts/main.js
:
function updateSubscriptionOnServer(subscription) {
// TODO: Send subscription to application server
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}
實戰演練
前往 [Push Codelab] (推送程式碼研究室) 分頁,重新整理頁面,然後按一下按鈕。這時畫面上會出現下列權限提示:
如果您授予權限,主控台上應該會顯示「User is subscribed
」。該按鈕的文字會變更為 [停用推送訊息],您將可以在頁面底部以 JSON 資料的形式查看訂閱。
您尚未處理權限要求,就是當使用者封鎖權限要求時,會發生什麼情況。這項設定需要特別注意,因為如果使用者封鎖權限,您的網頁應用程式將無法重新顯示權限提示,而且使用者無法訂閱。您必須至少停用按鈕,讓使用者知道無法使用。
處理此情況的顯而易見,是位於 updateBtn()
函式中。您只需要檢查 Notification.permission
值,如下所示:
function updateBtn() {
if (Notification.permission === 'denied') {
pushButton.textContent = 'Push Messaging Blocked';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;
}
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
您知道權限是 denied
,表示使用者無法訂閱,而且無法採取其他行動,因此永久停用按鈕是最好的方法。
實戰演練
由於您已經在上一個步驟中授權了網頁應用程式,因此需要按一下網址列中圓圈中的 [i],並將「通知」權限變更為 [使用全域預設 (詢問)]。
變更這項設定後,請重新整理頁面,然後按一下 [啟用推送訊息] 按鈕,然後在權限對話方塊中選取 [封鎖]。這個按鈕將停用,並顯示「禁止發送簡訊」文字。
本次異動生效後,您現在可以將使用者訂閱,並處理可能的權限情境。
在瞭解如何傳送後端推送訊息之前,您必須考量訂閱使用者收到推送訊息的實際狀況。
當您觸發推送訊息時,瀏覽器會接收推送訊息,並判斷推送工作的目標服務工作站、喚醒該服務工作站,以及分派推送事件。您必須監聽這個事件,系統才會顯示通知。
請將下列程式碼新增到 sw.js
檔案中:
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
event.waitUntil(self.registration.showNotification(title, options));
});
我們來逐步瀏覽這個程式碼。您可以新增事件監聽器,藉此監聽服務工作站中的 push
個事件:
self.addEventListener('push', ... );
(除非您之前已經與 Web Workers 互動,否則 self
可能是新的應用程式。在 Service Worker 檔案中,self
會參照 Service Worker 本身。)
當系統收到推送訊息時,系統會呼叫事件監聽器,而您可以在服務工作人員的 registration
屬性上呼叫 showNotification()
以建立通知。「showNotification()
」需要「title
」;您也可以為其指派 options
物件,以設定內文、圖示和標記。(只有 Android 撰寫時可使用徽章)。
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
self.registration.showNotification(title, options);
「push
」事件處理作業的最後一步是「event.waitUntil()
」。這個方法會保證瀏覽器啟用服務工作站,讓服務工作人員持續運作,直到傳遞承諾已解決為止。
為了讓程式碼更容易理解,您可以改寫程式碼:
const notificationPromise = self.registration.showNotification(title, options);
event.waitUntil(notificationPromise);
現在您已經完成推送事件,接著來測試推送事件。
實戰演練
在服務工作站中使用推送事件處理功能,您可以觸發偽造的推送事件,以測試收到訊息時會發生什麼事。
在您的網頁應用程式中訂閱推送訊息,並確認主控台顯示「User IS subscribed
」。在開發人員工具的「Application」(應用程式) 面板中,按一下「Service Workers」(服務工作站) 分頁下的 [Push] (推送) 按鈕:
按下 [推送] 後,您應該會看到類似以下的通知:
注意:如果這個步驟無法執行,請嘗試使用「開發人員工具」應用程式面板中的 [取消註冊] 連結取消註冊服務工作站,等待服務人員停止,然後重新載入頁面。
只要按一下其中一則通知,您就會發現沒有任何事。監聽服務工作站中的 notificationclick
事件,即可處理通知點擊。
首先,在 sw.js
中新增 notificationclick
事件監聽器:
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click received.');
event.notification.close();
event.waitUntil(
clients.openWindow('https://developers.google.com/web')
);
});
使用者點擊通知時,系統會呼叫 notificationclick
事件監聽器。
程式碼首先會關閉所點擊的通知:
event.notification.close();
接著開啟新視窗或新分頁,載入網址 https://developers.google.com/web
。可以變更這項設定。
event.waitUntil(
clients.openWindow('https://developers.google.com/web/')
);
event.waitUntil()
會確保瀏覽器在顯示新視窗或新分頁之前,才終止服務工作站。
實戰演練
再次嘗試在開發人員工具中觸發推送訊息,然後點選通知。系統隨即將關閉通知功能,並會開啟新分頁。
您發現自己的網頁應用程式能夠使用開發人員工具顯示通知,也想瞭解如何點擊關閉通知。下一步是傳送實際的推送訊息。
一般而言,這需要從網頁傳送訂閱到後端。接著,後端會藉由對訂閱項目中的端點發出 API 呼叫來觸發推送訊息。
這超出此程式碼研究室的範圍,但您可以透過夥伴網站 (web-push-codelab.glitch.me) 觸發實際的推送訊息。將訂閱項目貼到頁面底部:
然後貼到「訂閱收件者」文字區域中的隨播廣告素材網站:
在「Text to Send」(要傳送的文字) 之下,新增您要透過推送訊息傳送的字串。
按一下 [傳送推送訊息] 按鈕。
你隨即會收到推播通知。您使用的文字會記錄在控制台中。
如此一來,您就能測試及接收資料,並且操控搜尋結果。
隨附應用程式是使用 web-push 程式庫傳送訊息的節點伺服器。建議您查看 GitHub 上的 web-push-libs 機構,看看有哪些程式庫可以傳送推送訊息給您。這樣可以處理許多詳細資料,以觸發推送訊息。
您可以前往這裡查看隨播廣告網站的所有程式碼。
但有一件事是能夠讓使用者取消訂閱,方法是呼叫 PushSubscription
上的 unsubscribe()
。
返回您的 scripts/main.js
檔案,將 initializeUI()
中的 pushButton
點擊接聽器變更為以下內容:
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
unsubscribeUser();
} else {
subscribeUser();
}
});
請注意,您將會呼叫新的函式 unsubscribeUser()
。在這個函式中,您會取得目前的訂閱項目並呼叫 unsubscribe()
。將下列程式碼加進 scripts/main.js
:
function unsubscribeUser() {
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
});
}
我們來逐步說明這個函式。
首先,您可以呼叫 getSubscription()
,取得目前的訂閱:
swRegistration.pushManager.getSubscription()
這會傳回承諾使用 PushSubscription
解析的承諾產品;否則傳回 null
。如有訂閱項目,請呼叫 unsubscribe()
,讓 PushSubscription
無效。
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
// TODO: Tell application server to delete subscription
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
呼叫 unsubscribe()
會傳回承諾使用合約,因為系統可能需要一段時間才能完成作業。您聲明瞭這項承諾,因此鏈結中的下一個 then()
會等待 unsubscribe()
完成。您也可以新增擷取處理常式,以在發生錯誤時呼叫 unsubscribe()
結果。之後您就可以更新使用者介面。
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
})
實戰演練
您應該能在網路應用程式中按下 [啟用推播訊息] 或 [停用推送訊息功能],該記錄會顯示已訂閱及取消訂閱的使用者。
恭喜您完成這個程式碼研究室!
本程式碼研究室說明瞭如何在網路應用程式中新增推播通知,協助您順利上手。如要進一步瞭解網路通知可執行的動作,請參閱這些文件。
如果您想在網站上部署推播通知,建議您為採用舊版瀏覽器或採用 GCM 規定的標準瀏覽器新增支援。按這裡即可瞭解詳情。