Lớp học lập trình: Xây dựng ứng dụng thông báo đẩy

Kate Jeffreys
Kate Jeffreys

Lớp học lập trình này sẽ hướng dẫn bạn từng bước tạo ứng dụng thông báo đẩy. Khi kết thúc lớp học lập trình này, bạn sẽ có một ứng dụng:

  • Đăng ký nhận thông báo đẩy cho người dùng.
  • Nhận và hiển thị thông báo đẩy dưới dạng thông báo.
  • Huỷ đăng ký nhận thông báo đẩy của người dùng.

Lớp học lập trình này tập trung vào việc giúp bạn học qua thực hành và không đề cập nhiều về các khái niệm. Hãy xem phần Thông báo đẩy hoạt động như thế nào? để tìm hiểu về các khái niệm về thông báo đẩy.

Mã máy chủ của lớp học lập trình này đã hoàn tất. Bạn sẽ chỉ triển khai ứng dụng trong lớp học lập trình này. Để tìm hiểu cách triển khai máy chủ thông báo đẩy, hãy xem Lớp học lập trình: Tạo máy chủ thông báo đẩy.

Hãy tham khảo push-notifications-client-codelab-complete (nguồn) để xem mã đầy đủ.

Khả năng tương thích với trình duyệt

Lớp học lập trình này tương thích với các tổ hợp hệ điều hành và trình duyệt sau đây:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Android: Chrome, Firefox

Lớp học lập trình này được biết là không hoạt động với các hệ điều hành (hoặc các tổ hợp hệ điều hành và trình duyệt) sau đây:

  • macOS: Brave, Edge, Safari
  • iOS

Thiết lập

Nhận bản sao có thể chỉnh sửa của mã

Trình soạn thảo mã mà bạn thấy ở bên phải các hướng dẫn này sẽ được gọi là Giao diện người dùng Glitch (Giao diện người dùng Glitch) trong suốt lớp học lập trình này.

  1. Nhấp vào Remix để chỉnh sửa (Remix) để chỉnh sửa dự án.

Thiết lập phương thức xác thực

Để thông báo đẩy hoạt động, bạn cần thiết lập máy chủ và ứng dụng khách bằng các khoá xác thực. Hãy xem bài viết Ký các yêu cầu về giao thức đẩy trên web để tìm hiểu lý do.

  1. Trong giao diện người dùng nhiễu, hãy nhấp vào Tools (Công cụ), sau đó nhấp vào Terminal (Thiết bị đầu cuối) để mở cửa sổ dòng lệnh nhiễu.
  2. Trong cửa sổ Glitch Terminal, hãy chạy npx web-push generate-vapid-keys. Sao chép khoá riêng tư và các giá trị khoá công khai.
  3. Trong giao diện người dùng Glitch, hãy mở .env rồi cập nhật VAPID_PUBLIC_KEYVAPID_PRIVATE_KEY. Đặt VAPID_SUBJECT thành mailto:test@test.test. Tất cả các giá trị này phải được đặt trong dấu ngoặc kép. Sau khi cập nhật, tệp .env sẽ có dạng như sau:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Đóng Cửa sổ Glitch Terminal.
  1. Mở public/index.js.
  2. Thay thế VAPID_PUBLIC_KEY_VALUE_HERE bằng giá trị của khoá công khai.

Đăng ký một trình chạy dịch vụ

Cuối cùng, ứng dụng của bạn sẽ cần một trình chạy dịch vụ để nhận và hiển thị thông báo. Tốt nhất là bạn nên đăng ký nhân viên dịch vụ càng sớm càng tốt. Hãy xem bài viết Nhận và hiển thị tin nhắn được đẩy dưới dạng thông báo để biết thêm thông tin.

  1. Thay thế nhận xét // TODO add startup logic here bằng mã sau:
// TODO add startup logic here
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('./service-worker.js').then(serviceWorkerRegistration => {
    console.info('Service worker was registered.');
    console.info({serviceWorkerRegistration});
  }).catch(error => {
    console.error('An error occurred while registering the service worker.');
    console.error(error);
  });
  subscribeButton.disabled = false;
} else {
  console.error('Browser does not support service workers or push messages.');
}

subscribeButton.addEventListener('click', subscribeButtonHandler);
unsubscribeButton.addEventListener('click', unsubscribeButtonHandler);
  1. Để xem trước trang web, hãy nhấn vào View App (Xem ứng dụng), sau đó nhấn vào Fullscreen toàn màn hình (Toàn màn hình).
  1. Nhấn tổ hợp phím "Control+Shift+J" (hoặc "Command+Option+J" trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Bảng điều khiển. Bạn sẽ thấy thông báo Service worker was registered. được ghi vào Console.

Yêu cầu quyền gửi thông báo đẩy

Bạn không được yêu cầu quyền gửi thông báo đẩy khi tải trang. Thay vào đó, giao diện người dùng phải hỏi người dùng xem họ có muốn nhận thông báo đẩy hay không. Sau khi họ xác nhận một cách rõ ràng (ví dụ: bằng một lần nhấp vào nút), bạn có thể bắt đầu quy trình chính thức để nhận quyền gửi thông báo đẩy từ trình duyệt.

  1. Trong giao diện người dùng nhiễu, hãy nhấp vào View Source (Xem nguồn) để quay lại mã của bạn.
  2. Trong public/index.js, hãy thay thế nhận xét // TODO trong subscribeButtonHandler() bằng mã sau:
// TODO
// Prevent the user from clicking the subscribe button multiple times.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
  1. Quay lại thẻ ứng dụng rồi nhấp vào Đăng ký ứng dụng đẩy. Trình duyệt hoặc hệ điều hành của bạn có thể sẽ hỏi xem bạn có muốn cho phép trang web gửi thông báo đẩy cho bạn hay không. Nhấp vào Allow (Cho phép) (hoặc bất kỳ cụm từ nào tương đương mà trình duyệt/hệ điều hành của bạn sử dụng). Trong Bảng điều khiển, bạn sẽ thấy một thông báo cho biết yêu cầu được chấp nhận hay bị từ chối.

Đăng ký nhận thông báo đẩy

Quy trình thuê bao bao gồm việc tương tác với một dịch vụ web do nhà cung cấp trình duyệt kiểm soát, được gọi là dịch vụ đẩy. Sau khi nhận được thông tin về gói thuê bao thông báo đẩy, bạn cần gửi thông tin đó đến máy chủ và để máy chủ lưu trữ thông tin đó trong cơ sở dữ liệu về lâu dài. Xem phần Đăng ký cho ứng dụng nhận thông báo đẩy để biết thêm thông tin về quy trình đăng ký.

  1. Thêm mã được làm nổi bật sau đây vào subscribeButtonHandler():
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
  console.info('User is already subscribed.');
  notifyMeButton.disabled = false;
  unsubscribeButton.disabled = false;
  return;
}
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY)
});
notifyMeButton.disabled = false;
fetch('/add-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(subscription)
});

Tuỳ chọn userVisibleOnly phải là true. Một ngày nào đó, có thể bạn sẽ đẩy thông báo mà không hiển thị thông báo mà người dùng nhìn thấy (thông báo đẩy ở chế độ im lặng) nhưng các trình duyệt hiện không cho phép tính năng đó do vấn đề về quyền riêng tư.

Giá trị applicationServerKey dựa trên hàm hiệu dụng chuyển đổi chuỗi base64 thành Uint8Array. Giá trị này được dùng để xác thực giữa máy chủ của bạn và dịch vụ đẩy.

Huỷ đăng ký nhận thông báo đẩy

Sau khi người dùng đăng ký nhận thông báo đẩy, giao diện người dùng của bạn cần cung cấp cách huỷ đăng ký trong trường hợp người dùng đổi ý và không muốn nhận thông báo đẩy nữa.

  1. Thay thế nhận xét // TODO trong unsubscribeButtonHandler() bằng mã sau:
// TODO
const registration = await navigator.serviceWorker.getRegistration();
const subscription = await registration.pushManager.getSubscription();
fetch('/remove-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({endpoint: subscription.endpoint})
});
const unsubscribed = await subscription.unsubscribe();
if (unsubscribed) {
  console.info('Successfully unsubscribed from push notifications.');
  unsubscribeButton.disabled = true;
  subscribeButton.disabled = false;
  notifyMeButton.disabled = true;
}

Nhận thông báo đẩy và hiển thị dưới dạng thông báo

Như đã đề cập trước đó, bạn cần một trình chạy dịch vụ để xử lý việc nhận và hiển thị thông báo được đẩy đến ứng dụng từ máy chủ của bạn. Hãy xem bài viết Nhận và hiển thị tin nhắn được đẩy dưới dạng thông báo để biết thêm chi tiết.

  1. Mở public/service-worker.js và thay thế nhận xét // TODO trong trình xử lý sự kiện push của trình chạy dịch vụ bằng mã sau đây:
// TODO
let data = event.data.json();
const image = 'https://cdn.glitch.com/614286c9-b4fc-4303-a6a9-a4cef0601b74%2Flogo.png?v=1605150951230';
const options = {
  body: data.options.body,
  icon: image
}
self.registration.showNotification(
  data.title, 
  options
);
  1. Quay lại thẻ ứng dụng.
  2. Nhấp vào Thông báo cho tôi. Bạn sẽ nhận được thông báo đẩy.
  3. Hãy thử mở URL của thẻ ứng dụng trên các trình duyệt khác (hoặc thậm chí là các thiết bị khác), thực hiện quy trình đăng ký rồi nhấp vào Thông báo tất cả. Bạn sẽ nhận được cùng một thông báo đẩy trên tất cả các trình duyệt mà bạn đã đăng ký. Tham khảo lại phần Khả năng tương thích với trình duyệt để xem danh sách các tổ hợp trình duyệt/hệ điều hành được xác định là hoạt động hoặc không hoạt động.

Bạn có thể tuỳ chỉnh thông báo theo nhiều cách. Xem các tham số của ServiceWorkerRegistration.showNotification() để tìm hiểu thêm.

Mở URL khi người dùng nhấp vào thông báo

Trong thực tế, có thể bạn sẽ sử dụng thông báo như một cách để thu hút lại người dùng và nhắc họ truy cập vào trang web của bạn. Để làm việc đó, bạn cần định cấu hình trình chạy dịch vụ thêm một chút.

  1. Thay thế nhận xét // TODO trong trình xử lý sự kiện notificationclick của trình chạy dịch vụ bằng mã sau:
// TODO
event.notification.close();
event.waitUntil(self.clients.openWindow('https://web.dev'));
  1. Quay lại thẻ ứng dụng, gửi cho chính bạn một thông báo khác rồi nhấp vào thông báo đó. Trình duyệt của bạn sẽ mở một thẻ mới và tải https://web.dev.

Các bước tiếp theo