Web push notification
Bài đăng này đã không được cập nhật trong 4 năm
Notification
là những thông báo từ những application
được hiển thị trên các thiết bị của người dùng(Phone, Browser) ngay cả khi application
đó không được chạy. Bài viết này chúng ta sẽ tìm hiểu cơ chế push notification
trên các trình duyệt (Push notification on the web
) .
Push Notifications on the web
Push notification
giúp các application
trên browsers
tăng tương tác với user
hơn, từ những việc như thông báo tới user
những thông báo quan trọng, chuyển hướng user
tới site
nếu notification
được click, hoặc những notification popup
được thêm những action button
giúp user
có thể thao tác ngay trên đó mà không cần chuyến hướng tới website
.
Concepts
- Notifications API:
API
được sử dụng để hiển thị các notification tới phía người dùng - Push API: hỗ trợ các phương thức đăng ký
app
vớibrowser
push service và nhận cácpush messages
trong service worker - Push service: Một hệ thống có nhiệm vụ chuyển hướng các
push messages
từserver
tới cácclients
(browsers
) thông qua Web Push Protocol. Mỗibrowser
đều có hỗ trợpush service
của riêng nó. - Service worker: Ở bài post trước mình đã nói về
service worker
, nhiệm vụ củaservice worker
ở đây là được chạy ở background, xử lý cácpush messages
nhận được từserver
.
Flow
Để thực hiện push notification
trên browser
, ta cần phải yêu cầu quyền từ phía user
(cung cấp bởi Notification API
):
Notification.requestPermission(function(status) {
console.log('Notification permission status:', status);
});
Sau khi trang web được grant permission
, ảnh trên minh họa luồng thực hiện cho push notification
:
- Trước tiên, trang web cần register Service worker
- Nếu
register
thành công,browser
sẽ trả về mộtServiceWorkerRegistration
object. - Tiếp đó, webpage cần phải
subscribe
tớibrowser push service
:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js').then(function(reg) {
console.log('Service Worker Registered!', reg);
reg.pushManager.getSubscription().then(function(sub) {
console.log('Subscription object: ', sub.endpoint);
}
});
})
.catch(function(err) {
console.log('Service Worker registration failed: ', err);
});
}
1 subcription object
được trả về có dạng:
{
"endpoint":"https://fcm.googleapis.com/fcm/send/dpH5lCsTSSM:APA91bHqjZxM0VImWWqDRN7U0a3AycjUf4O-byuxb_wJsKRaKvV_iKw56s16ekq6FUqoCF7k2nICUpd8fHPxVTgqLunFeVeB9lLCQZyohyAztTH8ZQL9WCxKpA6dvTG_TUIhQUFq_n",
"keys": {
"p256dh":"BLQELIDm-6b9Bl07YrEuXJ4BL_YBVQ0dvt9NQGGJxIQidJWHPNa9YrouvcQ9d7_MqzvGS9Alz60SZNCG3qfpk=",
"auth":"4vQK-SvRAN5eo-8ASlrwA=="
}
}
endpoint URL
trả về sẽ khác nhau với mỗi browser
, là định danh của browser
đó, được sử dụng cho việc route tới đúng browser
khi gửi push message
.
Khi push message
được gửi đi từ server
, nó sẽ được gửi tới endpoint URL
này, được encrypted
với keys
(trong subcription object
) và được push service
gửi đúng tới browser
thông qua định danh ở endpoint URL
:
service worker
xử lý các push event
mỗi khi có push message
tới, hiển thị tới user
.
FCM push notification
Register service worker
Đầu tiên cần phải register
service worker
cho trang web của chúng ta với browser
:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./firebase-messaging-sw.js');
}
File firebase-messagin-sw.js
phải đặt setting ở ngoài thư mục root
trên server
. Trong Rails
có thể đặt trong thư mục public
.
Set up firebase
Cần set up firebase
ở code javascript
của webpage
. Ở đây mình xử lý trong Rails
.
- Cài đặt
firebase
library quayarn
:
$ yarn add firebase
- Init firebase:
// app/javascripts/packs/application.js
import * as firebase from 'firebase/app';
import 'firebase/messaging';
// init firebase
var firebaseConfig = {
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx,
authDomain: 'app_name.firebaseapp.com',
databaseURL: 'https://app_name.firebaseio.com',
projectId: 'app_name',
storageBucket: 'app_name.appspot.com',
messagingSenderId: "111111111111",
appId: "1:11111111111:web:d34d1206a3553c2b92f648",
measurementId: "XXXXXXXXXXXXX"
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
Phần firebaseConfig
bạn có thể xem tại đây.
- Get
FCM token
:
// Yêu cầu permission từ user, sau đó lấy log ra token
messaging.requestPermission().then(function() {
return messaging.getToken();
}).then(function(token) {
console.log(token);
})
token
ở đây là chuỗi token
trong endpoint URL format
ở trên, có nhiệm vụ định danh browser
hiện tại.
"endpoint":"https://fcm.googleapis.com/fcm/send/dpH5lCsTSSM:APA91bHqjZxM0VImWWqDRN7U0a3AycjUf4O-byuxb_wJsKRaKvV_iKw56s16ekq6FUqoCF7k2nICUpd8fHPxVTgqLunFeVeB9lLCQZyohyAztTH8ZQL9WCxKpA6dvTG_TUIhQUFq_n"
Sau khi log ra token
, ta sẽ gửi token
này về server
, sau đó server
sẽ khởi tạo message
muốn gửi và gửi push message
này tới firebase
.
Ở đây mình lấy token được log ra và gửi luôn tới firebase
.
- Server setup
Phía
server
cần tương tác để gửipush message
tớifirebase
. TrongRails
mình sẽ dùng gem fcm (hoặc bạn có thể test trực tiếp qua REST API)
gem 'fcm'
firebase
cần FCM_SERVER_KEY
để xác định application
của bạn, có thể lấy tại đây (Project credentials => Server key)
tạo FCM_COMPOSER
tiến hành gửi message:
FCM_COMPOSER = FCM.new(ENV['FCM_SERVER_KEY'])
tokens = [
"eXOGKT9WlA7u-OlZyRb_9U:APA91bFYctmLOiwTYfFR-UGMmx7CeOChxjzEBA4klZcgrAtJDGDSHPU8_6LAhgqq4LPA5zkH_7clNQ7K3Oti87G0izuln7S-RImOrgnK16DrIW7aJteBP3X5uEz9FeNk8a_2jRVKXu5-"
]
message = {
"notification": {
"title": "Hello world"
},
"data": {
"url": "https://viblo.asia/p/service-worker-Az45b4bOZxY"
}
}
FCM_COMPOSER.send(tokens, message)
- Receive message:
Ta cần xử lý hai trường hợp khi nhận message: Ở
foreground
vàbackground
.
Ở foreground
(khi user
đang truy cập webpage
), ta có thể nhận được message data và sử dụng Notification API để hiển thị popup notification
tới user
, thông qua hàm callback:
messaging.onMessage((payload) => {
console.log('Message received. ', payload);
// Notification API hiển thị noti
});
Khi user
trong trạng thái background
(bật tab khác hoặc app khác), message
tới được xử lý ở service worker
qua callback:
// ./firebase-messageing-sw.js
// version firebase ở đây phải đúng với firebase ở yarn
importScripts('https://www.gstatic.com/firebasejs/7.16.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.16.0/firebase-messaging.js');
// init firebase
var firebaseConfig = {
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx,
authDomain: 'app_name.firebaseapp.com',
databaseURL: 'https://app_name.firebaseio.com',
projectId: 'app_name',
storageBucket: 'app_name.appspot.com',
messagingSenderId: "111111111111",
appId: "1:11111111111:web:d34d1206a3553c2b92f648",
measurementId: "XXXXXXXXXXXXX"
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log("Message: " + payload.data.url);
console.log("Message: " + payload.notification.title);
return self.registration.showNotification("Hello", { body: "world" });
})
Lưu ý, khi handle message ở background(service worker
), nếu message gửi tới có chứa trường notification
thì browser
sẽ hiện thì popup thông báo mặc định của nó mà không qua hàm setBackgroundMessageHandler
, còn lại nếu message chỉ chứa data
thì sẽ xử lý bình thường.
Trên đây là tìm hiểu của mình về web push notification
. Cảm ơn mọi người đã theo dõi!
All rights reserved