Nếu bạn hỏi một nhóm nhà phát triển về những tính năng trên thiết bị di động bị thiếu trên web, thì thông báo đẩy luôn đứng đầu danh sách.
Thông báo đẩy cho phép người dùng chọn nhận thông tin cập nhật kịp thời từ các trang web mà họ yêu thích và cho phép bạn thu hút lại họ một cách hiệu quả bằng nội dung hấp dẫn, được cá nhân hoá.
Kể từ Chrome phiên bản 42, nhà phát triển có thể sử dụng Push API và Notification API.
Push API trong Chrome dựa vào một số công nghệ khác nhau, bao gồm cả Tệp kê khai ứng dụng web và Trình chạy dịch vụ. Trong bài đăng này, chúng ta sẽ xem xét từng công nghệ trong số này, nhưng chỉ ở mức tối thiểu để có thể chạy tính năng nhắn tin đẩy. Để hiểu rõ hơn về một số tính năng khác của tệp kê khai và chức năng ngoại tuyến của worker dịch vụ, vui lòng xem các đường liên kết ở trên.
Chúng ta cũng sẽ xem xét những nội dung sẽ được thêm vào API trong các phiên bản Chrome trong tương lai, và cuối cùng là phần Câu hỏi thường gặp.
Triển khai tính năng Thông báo đẩy cho Chrome
Phần này mô tả từng bước bạn cần hoàn tất để hỗ trợ tính năng thông báo đẩy trong ứng dụng web.
Đăng ký Trình chạy dịch vụ
Có một phần phụ thuộc là có một worker dịch vụ để triển khai thông báo đẩy cho web. Lý do là khi nhận được thông báo đẩy, trình duyệt có thể khởi động một worker dịch vụ chạy ở chế độ nền mà không cần mở trang và gửi một sự kiện để bạn có thể quyết định cách xử lý thông báo đẩy đó.
Dưới đây là ví dụ về cách đăng ký worker dịch vụ trong ứng dụng web. Khi đăng ký thành công, chúng ta sẽ gọi initialiseState() mà chúng ta sẽ đề cập đến trong phần sau.
var isPushEnabled = false;
…
window.addEventListener('load', function() {
var pushButton = document.querySelector('.js-push-button');
pushButton.addEventListener('click', function() {
if (isPushEnabled) {
unsubscribe();
} else {
subscribe();
}
});
// Check that service workers are supported, if so, progressively
// enhance and add push messaging support, otherwise continue without it.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(initialiseState);
} else {
console.warn('Service workers aren\'t supported in this browser.');
}
});
Trình xử lý lượt nhấp vào nút sẽ đăng ký hoặc huỷ đăng ký người dùng nhận thông báo đẩy. isPushEnabled là một biến toàn cục chỉ theo dõi xem thông báo đẩy hiện có được đăng ký hay không. Các biến này sẽ được tham chiếu trong suốt các đoạn mã.
Sau đó, chúng ta kiểm tra để đảm bảo rằng trình chạy dịch vụ được hỗ trợ trước khi đăng ký tệp service-worker.js
có logic để xử lý thông báo đẩy. Ở đây, chúng ta chỉ cần cho trình duyệt biết rằng tệp JavaScript này là worker dịch vụ cho trang web của chúng ta.
Thiết lập trạng thái ban đầu
Sau khi đăng ký worker dịch vụ, chúng ta cần thiết lập trạng thái của giao diện người dùng.
Người dùng sẽ mong muốn có một giao diện người dùng đơn giản để bật hoặc tắt thông báo đẩy cho trang web của bạn, đồng thời họ muốn giao diện người dùng đó luôn cập nhật mọi thay đổi xảy ra. Nói cách khác, nếu họ bật thông báo đẩy cho trang web của bạn, rời đi và quay lại sau một tuần, giao diện người dùng của bạn sẽ làm nổi bật rằng thông báo đẩy đã được bật.
Bạn có thể xem một số nguyên tắc về trải nghiệm người dùng trong tài liệu này. Trong bài viết này, chúng ta sẽ tập trung vào các khía cạnh kỹ thuật.
Tại thời điểm này, bạn có thể nghĩ rằng chỉ có hai trạng thái để xử lý, đó là bật hoặc tắt. Tuy nhiên, bạn cần cân nhắc một số trạng thái khác liên quan đến thông báo.
Có một số API mà chúng ta cần kiểm tra trước khi bật nút. Nếu mọi thứ đều được hỗ trợ, chúng ta có thể bật giao diện người dùng và đặt trạng thái ban đầu để cho biết liệu người dùng có đăng ký nhận thông báo đẩy hay không.
Vì hầu hết các bước kiểm tra này đều khiến giao diện người dùng bị vô hiệu hoá, nên bạn nên đặt trạng thái ban đầu thành vô hiệu hoá. Điều này cũng giúp tránh mọi nhầm lẫn nếu có vấn đề với JavaScript của trang, chẳng hạn như không thể tải tệp JS xuống hoặc người dùng đã tắt JavaScript.
<button class="js-push-button" disabled>
Enable Push Messages
</button>
Với trạng thái ban đầu này, chúng ta có thể thực hiện các bước kiểm tra nêu trên trong phương thức initialiseState()
, tức là sau khi đăng ký worker dịch vụ.
// Once the service worker is registered set the initial state
function initialiseState() {
// Are Notifications supported in the service worker?
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notifications aren\'t supported.');
return;
}
// Check the current Notification permission.
// If its denied, it's a permanent block until the
// user changes the permission
if (Notification.permission === 'denied') {
console.warn('The user has blocked notifications.');
return;
}
// Check if push messaging is supported
if (!('PushManager' in window)) {
console.warn('Push messaging isn\'t supported.');
return;
}
// We need the service worker registration to check for a subscription
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// Do we already have a push message subscription?
serviceWorkerRegistration.pushManager.getSubscription()
.then(function(subscription) {
// Enable any UI which subscribes / unsubscribes from
// push messages.
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = false;
if (!subscription) {
// We aren't subscribed to push, so set UI
// to allow the user to enable push
return;
}
// Keep your server in sync with the latest subscriptionId
sendSubscriptionToServer(subscription);
// Set your UI to show they have subscribed for
// push messages
pushButton.textContent = 'Disable Push Messages';
isPushEnabled = true;
})
.catch(function(err) {
console.warn('Error during getSubscription()', err);
});
});
}
Dưới đây là thông tin tổng quan ngắn gọn về các bước này:
- Chúng ta kiểm tra để đảm bảo
showNotification
có trong nguyên mẫu ServiceWorkerRegistration. Nếu không có thông báo này, chúng ta sẽ không thể hiển thị thông báo từ trình chạy dịch vụ khi nhận được thông báo đẩy. - Chúng ta kiểm tra
Notification.permission
hiện tại để đảm bảo rằng đó không phải là"denied"
. Nếu quyền bị từ chối, bạn sẽ không thể hiển thị thông báo cho đến khi người dùng thay đổi quyền theo cách thủ công trong trình duyệt. - Để kiểm tra xem tính năng nhắn tin đẩy có được hỗ trợ hay không, chúng ta kiểm tra để đảm bảo
PushManager
có sẵn trong đối tượng cửa sổ. - Cuối cùng, chúng ta đã sử dụng
pushManager.getSubscription()
để kiểm tra xem chúng ta có gói thuê bao hay không. Nếu có, chúng tôi sẽ gửi thông tin đăng ký đến máy chủ để đảm bảo chúng tôi có thông tin chính xác và thiết lập giao diện người dùng để cho biết tính năng nhắn tin đẩy đã được bật hay chưa. Chúng ta sẽ xem xét thông tin chi tiết có trong đối tượng thuê bao ở phần sau của bài viết này.
Chúng ta đợi cho đến khi navigator.serviceWorker.ready
được phân giải để kiểm tra gói thuê bao và bật nút đẩy vì chỉ sau khi worker dịch vụ hoạt động, bạn mới có thể thực sự đăng ký nhận thông báo đẩy.
Bước tiếp theo là xử lý khi người dùng muốn bật thông báo đẩy, nhưng trước khi có thể làm việc này, chúng ta cần thiết lập một dự án trên Google Developer Console và thêm một số tham số vào tệp kê khai để sử dụng Firebase Cloud Messaging (FCM), trước đây gọi là Google Cloud Messaging (GCM).
Tạo dự án trên Bảng điều khiển dành cho nhà phát triển Firebase
Chrome sử dụng FCM để xử lý việc gửi và phân phối thông báo đẩy; tuy nhiên, để sử dụng API FCM, bạn cần thiết lập một dự án trên Bảng điều khiển dành cho nhà phát triển Firebase.
Các bước sau đây dành riêng cho Chrome, Opera cho Android và Trình duyệt Samsung. Các trình duyệt này sử dụng FCM. Chúng ta sẽ thảo luận về cách hoạt động của tính năng này trong các trình duyệt khác ở phần sau của bài viết.
Tạo Dự án nhà phát triển Firebase mới
Để bắt đầu, bạn cần tạo một dự án mới trên https://console.firebase.google.com/ bằng cách nhấp vào "Tạo dự án mới".
Thêm tên dự án, tạo dự án và bạn sẽ được chuyển đến trang tổng quan về dự án:
Trên trang tổng quan này, hãy nhấp vào biểu tượng bánh răng bên cạnh tên dự án ở góc trên cùng bên trái rồi nhấp vào "Cài đặt dự án".
Trên trang cài đặt, hãy nhấp vào thẻ "Thông báo trên đám mây".
Trang này chứa khoá API để gửi thông báo đẩy mà chúng ta sẽ sử dụng sau này, cũng như mã nhận dạng người gửi mà chúng ta cần đưa vào tệp kê khai ứng dụng web trong phần tiếp theo.
Thêm tệp kê khai ứng dụng web
Đối với thông báo đẩy, chúng ta cần thêm một tệp kê khai có trường gcm_sender_id để đăng ký thông báo đẩy thành công. Tham số này chỉ bắt buộc đối với Chrome, Opera cho Android và Trình duyệt Samsung để các trình duyệt này có thể sử dụng FCM / GCM.
Các trình duyệt này sử dụng gcm_sender_id khi đăng ký thiết bị của người dùng bằng FCM. Điều này có nghĩa là FCM có thể xác định thiết bị của người dùng và đảm bảo rằng mã nhận dạng người gửi của bạn khớp với khoá API tương ứng, đồng thời người dùng đã cho phép máy chủ của bạn gửi thông báo đẩy cho họ.
Dưới đây là một tệp kê khai cực kỳ đơn giản:
{
"name": "Push Demo",
"short_name": "Push Demo",
"icons": [{
"src": "images/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}],
"start_url": "/index.html?homescreen=1",
"display": "standalone",
"gcm_sender_id": "<Your Sender ID Here>"
}
Bạn cần đặt giá trị gcm_sender_id thành mã nhận dạng người gửi trong Dự án Firebase.
Sau khi bạn lưu tệp kê khai trong dự án (manifest.json là tên tốt), hãy tham chiếu tệp đó từ HTML bằng thẻ sau trong phần đầu trang.
<link rel="manifest" href="/manifest.json">
Nếu không thêm tệp kê khai web có các tham số này, bạn sẽ gặp trường hợp ngoại lệ khi cố gắng đăng ký người dùng để nhận thông báo đẩy, với lỗi "Registration failed - no sender id provided"
hoặc "Registration failed -
permission denied"
.
Đăng ký nhận thông báo đẩy
Giờ đây, khi đã thiết lập tệp kê khai, bạn có thể quay lại JavaScript của trang web.
Để đăng ký, bạn phải gọi phương thức subscribe() trên đối tượng PushManager mà bạn truy cập thông qua ServiceWorkerRegistration.
Thao tác này sẽ yêu cầu người dùng cấp cho nguồn gốc của bạn quyền gửi thông báo đẩy. Nếu không có quyền này, bạn sẽ không thể đăng ký thành công.
Nếu lời hứa do phương thức subscribe() trả về được phân giải, bạn sẽ được cung cấp một đối tượng PushSubscription chứa một điểm cuối.
Bạn nên lưu điểm cuối trên máy chủ của mình cho từng người dùng, vì bạn sẽ cần các điểm cuối này để gửi thông báo đẩy vào lúc khác.
Mã sau đây sẽ đăng ký người dùng để nhận tin nhắn đẩy:
function subscribe() {
// Disable the button so it can't be changed while
// we process the permission request
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// The subscription was successful
isPushEnabled = true;
pushButton.textContent = 'Disable Push Messages';
pushButton.disabled = false;
// TODO: Send the subscription.endpoint to your server
// and save it to send a push message at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
pushButton.disabled = true;
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
}
});
});
}
Tại thời điểm này, ứng dụng web của bạn đã sẵn sàng nhận thông báo đẩy, mặc dù sẽ không có gì xảy ra cho đến khi chúng ta thêm trình nghe sự kiện đẩy vào tệp worker của dịch vụ.
Trình nghe sự kiện đẩy của trình chạy dịch vụ
Khi nhận được thông báo đẩy (chúng ta sẽ thảo luận về cách thực sự gửi thông báo đẩy trong phần tiếp theo), một sự kiện đẩy sẽ được gửi trong worker dịch vụ. Tại thời điểm đó, bạn cần hiển thị một thông báo.
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
Mã này đăng ký trình nghe sự kiện đẩy và hiển thị thông báo có tiêu đề, nội dung, biểu tượng và thẻ thông báo được xác định trước.
Một điểm tinh tế cần làm nổi bật trong ví dụ này là phương thức event.waitUntil()
. Phương thức này nhận một lời hứa và kéo dài thời gian hoạt động của trình xử lý sự kiện (hoặc có thể coi là duy trì hoạt động của worker dịch vụ), cho đến khi lời hứa được giải quyết; Trong trường hợp này, lời hứa được truyền đến event.waitUntil
là Lời hứa được trả về từ showNotification()
.
Thẻ thông báo đóng vai trò là giá trị nhận dạng cho các thông báo riêng biệt. Nếu chúng ta gửi hai thông báo đẩy đến cùng một điểm cuối, với độ trễ ngắn giữa hai thông báo và hiển thị thông báo bằng cùng một thẻ, thì trình duyệt sẽ hiển thị thông báo đầu tiên và thay thế thông báo đó bằng thông báo thứ hai khi nhận được thông báo đẩy.
Nếu bạn muốn hiển thị nhiều thông báo cùng một lúc, hãy sử dụng một thẻ khác hoặc không sử dụng thẻ nào cả. Chúng ta sẽ xem xét một ví dụ hoàn chỉnh hơn về cách hiển thị thông báo ở phần sau của bài đăng này. Hiện tại, hãy đơn giản hoá mọi thứ và xem việc gửi thông báo đẩy có hiển thị thông báo này hay không.
Gửi thông báo đẩy
Chúng ta đã đăng ký nhận thông báo đẩy và worker dịch vụ của chúng ta đã sẵn sàng hiển thị thông báo. Vì vậy, đã đến lúc gửi thông báo đẩy thông qua FCM.
Điều này chỉ áp dụng cho các trình duyệt sử dụng FCM.
Khi bạn gửi biến PushSubscription.endpoint
đến máy chủ, điểm cuối cho FCM sẽ đặc biệt. URL này có một tham số ở cuối là registration_id
.
Ví dụ về điểm cuối:
https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
URL FCM là:
https://fcm.googleapis.com/fcm/send
registration_id
sẽ là:
APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
Điều này áp dụng riêng cho những trình duyệt sử dụng FCM. Trong trình duyệt thông thường, bạn chỉ cần lấy một điểm cuối và gọi điểm cuối đó theo cách chuẩn và điểm cuối đó sẽ hoạt động bất kể URL.
Điều này có nghĩa là trên máy chủ, bạn cần kiểm tra xem điểm cuối có dành cho FCM hay không và nếu có, hãy trích xuất registration_id. Để thực hiện việc này trong Python, bạn có thể làm như sau:
if endpoint.startswith('https://fcm.googleapis.com/fcm/send'):
endpointParts = endpoint.split('/')
registrationId = endpointParts[len(endpointParts) - 1]
endpoint = 'https://fcm.googleapis.com/fcm/send'
Sau khi có mã nhận dạng đăng ký, bạn có thể thực hiện lệnh gọi đến API FCM. Bạn có thể tìm thấy tài liệu tham khảo về API FCM tại đây.
Sau đây là những khía cạnh chính cần nhớ khi gọi FCM:
- Bạn phải đặt tiêu đề Authorization (Uỷ quyền) có giá trị là
key=<YOUR_API_KEY>
khi gọi API, trong đó<YOUR_API_KEY>
là khoá API của dự án Firebase.- FCM sử dụng khoá API để tìm mã nhận dạng người gửi thích hợp, đảm bảo người dùng đã cấp quyền cho dự án của bạn và cuối cùng là đảm bảo địa chỉ IP của máy chủ có trong danh sách cho phép cho dự án đó.
- Tiêu đề
Content-Type
thích hợp củaapplication/json
hoặcapplication/x-www-form-urlencoded;charset=UTF-8
tuỳ thuộc vào việc bạn gửi dữ liệu dưới dạng JSON hay dữ liệu biểu mẫu. - Một mảng
registration_ids
– đây là mã nhận dạng đăng ký mà bạn sẽ trích xuất từ các điểm cuối của người dùng.
Vui lòng tham khảo tài liệu về cách gửi thông báo đẩy từ máy chủ của bạn. Tuy nhiên, để kiểm tra nhanh worker dịch vụ, bạn có thể sử dụng cURL để gửi thông báo đẩy đến trình duyệt.
Hãy hoán đổi <YOUR_API_KEY>
và <YOUR_REGISTRATION_ID>
trong lệnh cURL này bằng lệnh của riêng bạn và chạy lệnh đó từ một thiết bị đầu cuối.
Bạn sẽ thấy một thông báo tuyệt vời:
curl --header "Authorization: key=<YOUR_API_KEY>" --header
"Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
"{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
Khi phát triển logic phụ trợ, hãy nhớ rằng tiêu đề Uỷ quyền và định dạng của phần nội dung POST là dành riêng cho điểm cuối FCM, vì vậy, hãy phát hiện thời điểm điểm cuối là dành cho FCM và thêm tiêu đề và định dạng phần nội dung POST theo điều kiện. Đối với các trình duyệt khác (và hy vọng là Chrome trong tương lai), bạn cần triển khai Giao thức đẩy web.
Một điểm hạn chế của việc triển khai hiện tại của Push API trong Chrome là bạn không thể gửi bất kỳ dữ liệu nào bằng thông báo đẩy. Không, không có gì. Lý do là trong quá trình triển khai trong tương lai, dữ liệu tải trọng sẽ phải được mã hoá trên máy chủ của bạn trước khi được gửi đến điểm cuối nhắn tin đẩy. Bằng cách này, điểm cuối, bất kể nhà cung cấp dịch vụ đẩy nào, sẽ không thể dễ dàng xem nội dung của thông báo đẩy. Điều này cũng giúp bảo vệ khỏi các lỗ hổng khác như xác thực không tốt chứng chỉ HTTPS và các cuộc tấn công xen giữa giữa máy chủ và nhà cung cấp dịch vụ đẩy. Tuy nhiên, phương thức mã hoá này chưa được hỗ trợ, vì vậy, trong thời gian chờ đợi, bạn cần thực hiện một lệnh tìm nạp để lấy thông tin cần thiết nhằm điền thông báo.
Ví dụ đầy đủ hơn về sự kiện đẩy
Thông báo mà chúng ta đã thấy cho đến nay khá cơ bản và về mặt mẫu, thông báo này khá kém trong việc đề cập đến trường hợp sử dụng thực tế.
Thực tế, hầu hết mọi người sẽ muốn nhận một số thông tin từ máy chủ trước khi hiển thị thông báo. Đây có thể là dữ liệu để điền sẵn tiêu đề và thông báo của thông báo bằng một nội dung cụ thể, hoặc tiến thêm một bước và lưu một số trang hoặc dữ liệu vào bộ nhớ đệm để khi người dùng nhấp vào thông báo, mọi thứ sẽ có sẵn ngay khi trình duyệt mở ra, ngay cả khi mạng không hoạt động tại thời điểm đó.
Trong mã sau, chúng ta tìm nạp một số dữ liệu từ một API, chuyển đổi phản hồi thành một đối tượng và sử dụng đối tượng đó để điền thông báo.
self.addEventListener('push', function(event) {
// Since there is no payload data with the first version
// of push messages, we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(SOME_API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.error('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
var notificationTag = data.notification.tag;
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = URL_TO_DEFAULT_ICON;
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
Xin nhắc lại rằng event.waitUntil()
sẽ thực hiện một lời hứa dẫn đến lời hứa do showNotification()
trả về, nghĩa là trình nghe sự kiện của chúng ta sẽ không thoát cho đến khi lệnh gọi fetch()
không đồng bộ hoàn tất và thông báo xuất hiện.
Bạn sẽ thấy chúng tôi hiển thị thông báo ngay cả khi có lỗi. Lý do là nếu không, Chrome sẽ hiển thị thông báo chung của riêng mình.
Mở URL khi người dùng nhấp vào thông báo
Khi người dùng nhấp vào một thông báo, một sự kiện notificationclick
sẽ được gửi trong worker dịch vụ. Trong trình xử lý, bạn có thể thực hiện hành động thích hợp, chẳng hạn như lấy tiêu điểm một thẻ hoặc mở một cửa sổ có URL cụ thể:
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('/');
}
})
);
});
Ví dụ này mở trình duyệt đến thư mục gốc của nguồn gốc trang web, bằng cách lấy tiêu điểm là một thẻ cùng nguồn gốc hiện có (nếu có) và nếu không thì mở một thẻ mới.
Có một bài đăng dành riêng cho một số việc bạn có thể làm với Notification API tại đây.
Huỷ đăng ký thiết bị của người dùng
Bạn đã đăng ký thiết bị của người dùng và họ đang nhận được thông báo đẩy, nhưng làm cách nào để bạn có thể huỷ đăng ký?
Những việc chính cần làm để huỷ đăng ký thiết bị của người dùng là gọi phương thức unsubscribe()
trên đối tượng PushSubscription và xoá điểm cuối khỏi máy chủ của bạn (chỉ để bạn không gửi thông báo đẩy mà bạn biết sẽ không được nhận). Mã bên dưới thực hiện chính xác việc này:
function unsubscribe() {
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// To unsubscribe from push messaging, you need get the
// subscription object, which you can call unsubscribe() on.
serviceWorkerRegistration.pushManager.getSubscription().then(
function(pushSubscription) {
// Check we have a subscription to unsubscribe
if (!pushSubscription) {
// No subscription object, so set the state
// to allow the user to subscribe to push
isPushEnabled = false;
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
return;
}
var subscriptionId = pushSubscription.subscriptionId;
// TODO: Make a request to your server to remove
// the subscriptionId from your data store so you
// don't attempt to send them push messages anymore
// We have a subscription, so call unsubscribe on it
pushSubscription.unsubscribe().then(function(successful) {
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
isPushEnabled = false;
}).catch(function(e) {
// We failed to unsubscribe, this can lead to
// an unusual state, so may be best to remove
// the users data from your data store and
// inform the user that you have done so
console.log('Unsubscription error: ', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
});
}).catch(function(e) {
console.error('Error thrown while unsubscribing from push messaging.', e);
});
});
}
Cập nhật gói thuê bao
Các gói thuê bao có thể không đồng bộ giữa FCM và máy chủ của bạn. Đảm bảo máy chủ của bạn phân tích cú pháp nội dung phản hồi của yêu cầu gửi POST của API FCM, tìm kết quả error:NotRegistered
và canonical_id
, như được giải thích trong tài liệu về FCM.
Các gói thuê bao cũng có thể không đồng bộ giữa worker dịch vụ và máy chủ. Ví dụ: sau khi đăng ký/huỷ đăng ký thành công, một kết nối mạng không ổn định có thể khiến bạn không cập nhật được máy chủ; hoặc người dùng có thể thu hồi quyền gửi thông báo, điều này sẽ kích hoạt việc tự động huỷ đăng ký. Xử lý các trường hợp như vậy bằng cách định kỳ kiểm tra kết quả của serviceWorkerRegistration.pushManager.getSubscription()
(ví dụ: khi tải trang) và đồng bộ hoá kết quả đó với máy chủ. Bạn cũng có thể tự động đăng ký lại nếu không còn gói thuê bao và Notification.permission == 'granted'.
Trong sendSubscriptionToServer()
, bạn cần cân nhắc cách xử lý các yêu cầu mạng không thành công khi cập nhật endpoint
. Một giải pháp là theo dõi trạng thái của endpoint
trong một cookie để xác định xem máy chủ của bạn có cần thông tin chi tiết mới nhất hay không.
Tất cả các bước trên sẽ giúp bạn triển khai đầy đủ tính năng nhắn tin đẩy trên web trong Chrome 46. Vẫn còn một số tính năng theo thông số kỹ thuật sẽ giúp mọi việc trở nên dễ dàng hơn (chẳng hạn như API tiêu chuẩn để kích hoạt thông báo đẩy), nhưng bản phát hành này cho phép bạn bắt đầu xây dựng thông báo đẩy vào ứng dụng web ngay hôm nay.
Cách gỡ lỗi ứng dụng web
Trong khi triển khai thông báo đẩy, lỗi sẽ nằm ở một trong hai vị trí: trang hoặc worker dịch vụ.
Bạn có thể gỡ lỗi trong trang bằng cách sử dụng DevTools. Để gỡ lỗi các vấn đề về trình chạy dịch vụ, bạn có hai lựa chọn:
- Truy cập vào chrome://inspect > Service workers (chrome://kiểm tra > Trình chạy dịch vụ). Chế độ xem này không cung cấp nhiều thông tin ngoài các worker dịch vụ đang chạy.
- Truy cập vào chrome://serviceworker-internals. Tại đây, bạn có thể xem trạng thái của trình chạy dịch vụ và xem lỗi (nếu có). Trang này là tạm thời cho đến khi Công cụ cho nhà phát triển có một bộ tính năng tương tự.
Một trong những mẹo hay nhất mà tôi có thể chia sẻ với những người mới sử dụng worker là sử dụng hộp đánh dấu có tên "Mở cửa sổ DevTools và tạm dừng quá trình thực thi JavaScript khi khởi động worker để gỡ lỗi". Hộp đánh dấu này sẽ thêm một điểm ngắt ở đầu trình chạy dịch vụ và tạm dừng quá trình thực thi, cho phép bạn tiếp tục hoặc từng bước thực hiện tập lệnh trình chạy dịch vụ và xem liệu bạn có gặp vấn đề nào không.
Nếu có vẻ như có vấn đề giữa FCM và sự kiện đẩy của worker dịch vụ, thì bạn không thể làm gì nhiều để gỡ lỗi vấn đề này vì không có cách nào để bạn biết liệu Chrome có nhận được gì hay không. Điều quan trọng cần đảm bảo là phản hồi từ FCM thành công khi máy chủ của bạn thực hiện lệnh gọi API. Mã sẽ có dạng như sau:
{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}
Hãy lưu ý phản hồi "success": 1
. Nếu bạn thấy thông báo lỗi, thì điều đó cho thấy có gì đó không ổn với mã đăng ký FCM và thông báo đẩy không được gửi đến Chrome.
Gỡ lỗi Worker dịch vụ trên Chrome cho Android
Hiện tại, việc gỡ lỗi trình chạy dịch vụ trên Chrome cho Android không rõ ràng. Bạn cần chuyển đến chrome://inspect, tìm thiết bị của mình và tìm một mục danh sách có tên "Worker pid:...." (Mã nhận dạng của worker:....") có URL của worker dịch vụ.
Trải nghiệm người dùng cho thông báo đẩy
Nhóm Chrome đã tổng hợp một tài liệu về các phương pháp hay nhất cho trải nghiệm người dùng thông báo đẩy, cũng như một tài liệu trình bày một số trường hợp hiếm gặp khi làm việc với thông báo đẩy.
- Các phương pháp hay nhất về trải nghiệm người dùng liên quan đến quyền gửi thông báo đẩy
- Các trường hợp đặc biệt và biện pháp giảm thiểu đối với thông báo đẩy
Tương lai của tính năng Thông báo đẩy trên Chrome và Web mở
Phần này trình bày một số chi tiết về một số phần cụ thể của Chrome trong quá trình triển khai này mà bạn cần lưu ý và sự khác biệt giữa cách triển khai này với các cách triển khai trình duyệt khác.
Giao thức đẩy web và điểm cuối
Điểm hay của tiêu chuẩn Push API là bạn có thể lấy điểm cuối, chuyển các điểm cuối đó đến máy chủ và gửi thông báo đẩy bằng cách triển khai Giao thức đẩy web.
Giao thức đẩy web là một tiêu chuẩn mới mà các nhà cung cấp dịch vụ đẩy có thể triển khai, cho phép nhà phát triển không phải lo lắng về nhà cung cấp dịch vụ đẩy. Ý tưởng là việc này giúp bạn không cần đăng ký khoá API và gửi dữ liệu được định dạng đặc biệt, như bạn phải làm với FCM.
Chrome là trình duyệt đầu tiên triển khai Push API và FCM không hỗ trợ giao thức Web Push. Đó là lý do tại sao Chrome yêu cầu gcm_sender_id
và bạn cần sử dụng API REST cho FCM.
Mục tiêu cuối cùng của Chrome là chuyển sang sử dụng Giao thức đẩy web với Chrome và FCM.
Cho đến thời điểm đó, bạn cần phát hiện điểm cuối "https://fcm.googleapis.com/fcm/send" và xử lý điểm cuối này riêng biệt với các điểm cuối khác, tức là định dạng dữ liệu tải trọng theo cách cụ thể và thêm Khoá uỷ quyền.
Làm cách nào để triển khai Giao thức đẩy web?
Firefox Nightly hiện đang triển khai tính năng đẩy và có thể sẽ là trình duyệt đầu tiên triển khai Giao thức đẩy web.
Câu hỏi thường gặp
Thông số kỹ thuật ở đâu?
https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/
Tôi có thể ngăn thông báo trùng lặp nếu sự hiện diện trên web của tôi có nhiều nguồn gốc hoặc nếu tôi có cả sự hiện diện trên web và sự hiện diện gốc không?
Hiện tại chưa có giải pháp cho vấn đề này, nhưng bạn có thể theo dõi tiến trình trên Chromium.
Trường hợp lý tưởng là bạn có một loại mã nhận dạng cho thiết bị của người dùng, sau đó, ở phía máy chủ, hãy so khớp mã nhận dạng gói thuê bao của ứng dụng gốc và ứng dụng web, rồi quyết định gửi thông báo đẩy đến ứng dụng nào. Bạn có thể thực hiện việc này thông qua kích thước màn hình, mô hình thiết bị, chia sẻ khoá đã tạo giữa ứng dụng web và ứng dụng gốc, nhưng mỗi phương pháp đều có ưu và khuyết điểm.
Tại sao tôi cần có gcm_sender_id?
Điều này là bắt buộc để Chrome, Opera cho Android và Trình duyệt Samsung có thể sử dụng API Giải pháp gửi thông báo qua đám mây của Firebase (FCM). Mục tiêu là sử dụng giao thức Web Push khi tiêu chuẩn này được hoàn tất và FCM có thể hỗ trợ giao thức này.
Tại sao không sử dụng Web Sockets hoặc Sự kiện do máy chủ gửi (EventSource)?
Ưu điểm của việc sử dụng thông báo đẩy là ngay cả khi trang của bạn bị đóng, worker dịch vụ vẫn sẽ được đánh thức và có thể hiển thị thông báo. Web Sockets và EventSource sẽ bị đóng kết nối khi trang hoặc trình duyệt bị đóng.
Nếu tôi không cần phân phối sự kiện ở chế độ nền thì sao?
Nếu bạn không cần phân phối ở chế độ nền, thì Web Sockets là một lựa chọn tuyệt vời.
Khi nào tôi có thể sử dụng tính năng đẩy mà không hiển thị thông báo (tức là đẩy thầm ở chế độ nền)?
Hiện chưa có tiến trình về thời điểm ra mắt tính năng này, nhưng chúng tôi có ý định triển khai tính năng đồng bộ hoá ở chế độ nền. Mặc dù chưa được quyết định hoặc quy định, nhưng chúng tôi có một số nội dung thảo luận về việc bật tính năng đẩy không âm thanh bằng tính năng đồng bộ hoá ở chế độ nền.
Tại sao việc này yêu cầu HTTPS? Làm cách nào để khắc phục vấn đề này trong quá trình phát triển?
Trình chạy dịch vụ yêu cầu nguồn gốc an toàn để đảm bảo rằng tập lệnh của trình chạy dịch vụ là từ nguồn gốc dự kiến và không phải là do một cuộc tấn công giả mạo. Hiện tại, điều đó có nghĩa là sử dụng HTTPS trên các trang web đang hoạt động, mặc dù localhost sẽ hoạt động trong quá trình phát triển.
Hoạt động hỗ trợ trình duyệt diễn ra như thế nào?
Chrome hỗ trợ trong phiên bản ổn định và Mozilla đang triển khai tính năng đẩy trong Firefox Nightly. Hãy xem lỗi triển khai Push API để biết thêm thông tin và bạn có thể theo dõi cách triển khai Thông báo của họ tại đây.
Tôi có thể xoá một thông báo sau một khoảng thời gian nhất định không?
Hiện tại, bạn không thể làm việc này nhưng chúng tôi dự định sẽ hỗ trợ thêm để lấy danh sách thông báo hiện đang hiển thị. Nếu bạn có trường hợp sử dụng để đặt thời gian hết hạn cho thông báo sau khi thông báo đó được tạo, chúng tôi rất muốn biết trường hợp đó là gì. Vì vậy, vui lòng thêm bình luận và chúng tôi sẽ chuyển lại trường hợp đó cho nhóm Chrome.
Nếu chỉ cần ngừng gửi thông báo đẩy cho người dùng sau một khoảng thời gian nhất định và không quan tâm đến thời lượng hiển thị của thông báo, thì bạn có thể sử dụng thông số thời gian tồn tại (ttl) của FCM, tìm hiểu thêm tại đây.
Tính năng nhắn tin đẩy trong Chrome có những hạn chế gì?
Có một số hạn chế được nêu trong bài đăng này:
- Việc Chrome sử dụng CCM làm dịch vụ đẩy tạo ra một số yêu cầu độc quyền. Chúng tôi đang cùng nhau nỗ lực để xem liệu có thể gỡ bỏ một số hạn chế này trong tương lai hay không.
- Bạn phải hiển thị thông báo khi nhận được thông báo đẩy.
- Chrome trên máy tính có cảnh báo rằng nếu Chrome không chạy, thì bạn sẽ không nhận được thông báo đẩy. Điều này khác với ChromeOS và Android, nơi tin nhắn đẩy sẽ luôn được nhận.
Chúng ta không nên sử dụng Permissions API (API Quyền) phải không?
Permission API được triển khai trong Chrome, nhưng không nhất thiết phải có trong tất cả trình duyệt. Bạn có thể tìm hiểu thêm tại đây.
Tại sao Chrome không mở thẻ trước đó khi tôi nhấp vào một thông báo?
Vấn đề này chỉ ảnh hưởng đến những trang hiện không do trình chạy dịch vụ kiểm soát. Bạn có thể tìm hiểu thêm tại đây.
Điều gì sẽ xảy ra nếu thông báo đã lỗi thời vào thời điểm thiết bị của người dùng nhận được thông báo đẩy?
Bạn phải luôn hiển thị thông báo khi nhận được thông báo đẩy. Trong trường hợp bạn muốn gửi thông báo nhưng thông báo đó chỉ hữu ích trong một khoảng thời gian nhất định, bạn có thể sử dụng thông số "time_to_live" trên CCM để FCM không gửi thông báo đẩy nếu thông báo đó đã hết hạn.
Bạn có thể xem thêm thông tin chi tiết tại đây.
Điều gì sẽ xảy ra nếu tôi gửi 10 thông báo đẩy nhưng chỉ muốn thiết bị nhận một thông báo?
FCM có một tham số "collapse_key" mà bạn có thể sử dụng để yêu cầu FCM thay thế mọi thông báo đang chờ xử lý có cùng "collapse_key" bằng thông báo mới.