Anda dapat menemukan artikel tertanggal 2017 ... 2018 yang berfokus pada penggunaan sarana tingkat rendah untuk mengirim dan menerima pesan web push, misalnya, menggunakan pustaka web-push-libs / web-push . Pustaka ini masih berkembang, namun sekarang lebih mudah untuk bekerja dengan pustaka dari firebase.
Menyiapkan proyek firebase
Jadi, mari kita mulai dengan membuat proyek di firebase. Dengan konsol firebase terbuka , proyek baru perlu dibuat. Dalam Informasi Umum-> Pengaturan-> Pengaturan Umum-> Aplikasi Anda , Anda perlu membuat aplikasi web baru. Ini akan menghasilkan kode inisialisasi aplikasi web di sisi frontend:
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.19.0/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.19.0/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
Pada tab yang sama di konsol firebase Informasi umum- > Setelan- > Perpesanan Awan- > Kredensial untuk proyek -> Kunci server , kami menemukan kunci pribadi, yang dengannya Anda dapat mengirim pemberitahuan push melalui server firebase.
Mengirim pesan push web
Pengembang front-end dapat mengirim pesan push web mereka sendiri menggunakan perintah curl:
curl -X POST -H "Authorization: key=< >" -H "Content-Type: application/json" -d '{
"data": {
"title": "FCM Message",
"body": "This is an <i>FCM Message</i>",
"icon": "/static/plus.png",
"sound": "/static/push.mp3",
"click_action": "https://google.com",
},
"to": "< >"
}' https://fcm.googleapis.com/fcm/send
Mendapatkan kunci server dijelaskan di bagian Menyiapkan proyek firebase , dan mendapatkan token pendaftaran akan dijelaskan di bagian Mendapatkan token pendaftaran .
data vs payload pemberitahuan
Muatan dapat dikirim di bidang data atau pemberitahuan dari pesan push web. Untuk payload notifikasi, permintaannya akan terlihat seperti ini (untuk payload data, lihat permintaan di bagian Mengirim pesan push ):
curl -X POST -H "Authorization: key=< >" -H "Content-Type: application/json" -d '{
"notification": {
"title": "FCM Message",
"body": "This is an <i>FCM Message</i>",
"icon": "/static/plus.png",
"click_action": "https://google.com",
},
"to": "< >"
}' https://fcm.googleapis.com/fcm/send
data dan payload notifikasi memiliki dua perbedaan mendasar:
- payload notifikasi memiliki sekumpulan bidang yang ditentukan secara ketat, bidang tambahan akan diabaikan, sementara muatan data mengirim semua bidang ke frontend tanpa batasan.
- Jika browser web berada di latar belakang atau tautan aktif berisi situs pihak ketiga, push web payload notifikasi menampilkan pesan tanpa mentransfer kontrol ke pengendali kejadian onMessage, sedangkan web push muatan data selalu mentransfer kontrol ke pengendali kejadian onMessage, tetapi untuk untuk menampilkan pesan, Anda harus secara eksplisit membuat objek Notification. Jika web browser dalam keadaan aktif dan situs kita terbuka pada tab aktif, maka pengerjaan dengan data dan payload notifikasi tidak berbeda.
Membuat objek perpesanan
Untuk bekerja di frontend dengan pesan push web, Anda perlu membuat objek perpesanan:
const messaging = window.firebase.messaging();
Dalam kode ini,
firebaseini adalah objek global yang dibuat selama pemuatan library firebase dan diinisialisasi di sisi frontend seperti yang dijelaskan dalam Menyiapkan project firebase . Proyek ini dikembangkan di Vue.js. Oleh karena itu, menghubungkan skrip melalui elemen skrip html tampaknya tidak menjanjikan. Untuk menghubungkan skrip ini, saya menggunakan perpustakaan vue-plugin-load-script:
import Vue from "vue";
import LoadScript from "vue-plugin-load-script";
Vue.use(LoadScript);
var firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
Promise.resolve()
.then(() =>
Vue.loadScript(
"https://www.gstatic.com/firebasejs/7.14.0/firebase-app.js"
)
)
.then(() =>
Vue.loadScript(
"https://www.gstatic.com/firebasejs/7.14.0/firebase-messaging.js"
)
)
.then(() =>
Vue.loadScript(
"https://www.gstatic.com/firebasejs/7.14.0/firebase-analytics.js"
)
)
.then(() => {
window.firebase.initializeApp(firebaseConfig);
const messaging = window.firebase.messaging();
... // messaging
});
Memperoleh token pendaftaran
Token pendaftaran adalah pengenal yang secara unik mengidentifikasi perangkat dan browser web, sehingga memungkinkan pesan push web dikirim ke perangkat tertentu dan diproses oleh browser web tertentu:
Notification.requestPermission()
.then(permission => {
if (permission === "granted") {
messaging
.getToken()
.then(token => {
... //
});
} else {
console.log("Unable to get permission to notify.");
}
});
Dalam beberapa keadaan, token dapat diperbarui. Dan Anda perlu menangani acara pembaruan token:
messaging.onTokenRefresh(function() {
messaging
.getToken()
.then(function(refreshedToken) {
... //
});
});
Mengenai acara ini, saya punya pertanyaan - apakah relevan. Faktanya adalah bahwa bahkan sebelum pindah ke FCM, prosedur rotasi token berfungsi dengan GCM. Hal ini dijelaskan di pustaka Android dan secara tidak langsung dalam deskripsi operasi server, di mana setiap respons server berisi token kanonik dan harus terus-menerus diperiksa dan diubah (namun, ternyata, selain saya, respons tersebut jarang diikuti oleh siapa pun). Setelah pindah ke FCM, konsep seperti token kanonis tidak lagi digunakan (kemungkinan besar karena dalam praktiknya token tersebut jarang dilacak). Dalam hal ini, kasus di mana suatu peristiwa mungkin terjadi tidak sepenuhnya jelas
onTokenRefresh().
Acara OnMessage - versi sederhana
Saya akan langsung menjawab kenapa disederhanakan. Kami akan membuat setidaknya dua penyederhanaan. 1) Kami akan menggunakan payload notifikasi untuk menerima dan menampilkan pesan jika aplikasi berada di latar belakang tanpa pekerjaan tambahan. 2) Lupakan bahwa pada perangkat seluler, sistem keamanan tidak mengizinkan operator Notification () baru untuk dijalankan.
Jadi, seperti yang sudah kami katakan, untuk payload notifikasi, pesan push web datang dan ditampilkan tanpa partisipasi sedikit pun dari pengembang front-end (tentu saja, setelah mengirim token pendaftaran ke server). Masih perlu dipastikan apakah browser web dalam keadaan aktif dan situs terbuka di tab aktif:
messaging.onMessage(function(payload) {
const data = { ...payload.notification, ...payload.data };
const notificationTitle = data.title;
const notificationOptions = {
body: data.body,
icon: data.icon,
image: data.image,
click_action: data.click_action,
requireInteraction: true,
data
};
new Notification(payload.notification.title, payload.notification);
});
Menangani peristiwa menerima pesan push web di latar belakang
Di bagian ini, kita akan mulai bekerja dengan pekerja layanan. Dan ini, antara lain, berarti Anda perlu mengonfigurasi situs agar berfungsi menggunakan protokol https yang aman. Dan ini segera memperumit perkembangan selanjutnya. Oleh karena itu, untuk kasus sederhana, apa yang sudah dijelaskan sebelumnya sudah cukup.
Untuk bekerja dengan pustaka firebase, sebuah file bernama
firebase-messaging-sw.js. Nama file bisa berbeda, tetapi bagaimanapun juga itu harus ditempatkan di direktori root karena kekhasan perlindungan browser web (jika tidak, pekerja layanan ini tidak akan berfungsi untuk seluruh situs).
Sebagai aturan, penangan kejadian juga ditempatkan di file ini
notificationclick. Anda hampir tidak dapat menemukan sesuatu yang berbeda dari kode ini:
var firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
importScripts("https://www.gstatic.com/firebasejs/7.17.2/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.17.2/firebase-messaging.js");
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
const data = { ...payload.notification, ...payload.data };
const notificationTitle = data.title;
const notificationOptions = {
body: data.body,
icon: data.icon,
image: data.image,
requireInteraction: true,
click_action: data.click_action,
data
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
self.addEventListener("notificationclick", function(event) {
const target = event.notification.data.click_action;
event.notification.close();
event.waitUntil(
clients
.matchAll({
type: "window",
includeUncontrolled: true
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
console.log(client.url, client.focus);
if (client.url === target && "focus" in client) {
return client.focus();
}
}
return clients.openWindow(target);
})
);
});
Opsi untuk menangani acara onMessage dengan pekerja layanan
Izinkan saya mengingatkan Anda bahwa di bagian onMessage Event - versi yang disederhanakan, kami telah menjelaskan cara menangani pesan web push. Tetapi metode ini memiliki satu kelemahan yang signifikan - metode ini tidak berfungsi di perangkat seluler karena kekhasan sistem perlindungan browser web. Untuk mengatasi kelemahan ini, opsi pekerja layanan telah ditemukan, di mana objek Notification sudah disematkan, dan tidak perlu dibuat dengan operator baru:
messaging.onMessage(function(payload) {
play();
navigator.serviceWorker.register("/firebase-messaging-sw.js");
Notification.requestPermission(function(result) {
if (result === "granted") {
navigator.serviceWorker.ready
.then(function(registration) {
const data = { ...payload.notification, ...payload.data };
const notificationTitle = data.title;
const notificationOptions = {
body: data.body,
icon: data.icon,
image: data.image,
click_action: data.click_action,
requireInteraction: true,
data
};
return registration.showNotification(
notificationTitle,
notificationOptions
);
})
.catch(function(error) {
console.log("ServiceWorker registration failed", error);
});
}
});
});
Bunyi bip saat menerima pesan web push
Saya harus mengatakan bahwa kita praktis tidak memiliki kendali atas bagaimana pemberitahuan push akan ditampilkan di berbagai perangkat. Dalam beberapa kasus, ini akan menjadi pesan pop-up, dalam kasus lain, dorongan akan segera menuju ke "pelat" sistem, dan jika belum ada akting suara, itu hanya akan hilang ke klien. Dengan svuk, semuanya menjadi sangat sulit. Spesifikasi sebelumnya termasuk bidang suara, yang sebelumnya bertanggung jawab atas suara saat menerima pesan dorong web, tetapi saat ini tidak ada properti seperti itu. Dalam hal ini, saya menetapkan tujuan untuk membuat rekaman audio dorongan tersebut.
Deskripsi yang terkadang ditemui dengan pembuatan elemen audio html dan memanggil metode play () pada kenyataannya tidak berfungsi karena fitur keamanan browser web (hanya dapat dipanggil dengan satu klik dari pengguna sebenarnya). Tetapi ada juga AudioContext () - kami akan mengerjakannya:
const play = () => {
try {
const context = new AudioContext();
window
.fetch(soundUrl)
.then(response => response.arrayBuffer())
.then(arrayBuffer => context.decodeAudioData(arrayBuffer))
.then(audioBuffer => {
const source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect(context.destination);
source.start();
});
} catch (ex) {
console.log(ex);
}
};
Semuanya baik-baik saja, tetapi kami masih memiliki pekerja layanan yang tidak memiliki objek AudioContext (). Ingatlah bahwa semua pekerja berkomunikasi melalui pesan. Dan kemudian menerima kejadian dari pekerja layanan akan terlihat seperti ini:
try {
const broadcast = new BroadcastChannel("play");
broadcast.onmessage = play;
} catch (ex) {
console.log(ex) ;
}
Tentu saja, agar kode ini berfungsi, Anda memerlukan 1) Browser terbuka 2) Situs terbuka (meskipun tidak harus pada tab aktif). Tapi tidak ada cara lain.
Alih-alih kata penutup
Sekarang Anda bisa menghembuskan napas dan berkata, itu saja. Tapi ... Semua ini tidak berfungsi di safari - dan ini adalah topik lain yang terpisah dan didokumentasikan dengan buruk, meskipun beberapa artikel dapat ditemukan.
Tautan yang berguna
1) habr.com/ru/post/321924
apapacy@gmail.com
24 Agustus 2020