Jika menggunakan FCM API untuk membuat permintaan kirim secara terprogram, Anda mungkin mendapati bahwa, dari waktu ke waktu, Anda menyia-nyiakan resource dengan mengirimkan pesan ke perangkat yang tidak aktif dengan token pendaftaran yang sudah usang. Situasi ini dapat memengaruhi data pengiriman pesan yang dilaporkan di Firebase console atau data yang diekspor ke BigQuery, yang ditampilkan sebagai penurunan rasio penayangan yang drastis (tetapi tidak valid). Panduan ini berisi pembahasan mengenai beberapa langkah yang dapat Anda ambil untuk membantu memastikan penargetan pesan yang efisien dan pelaporan pengiriman yang valid.
Token pendaftaran yang sudah usang dan tidak berlaku lagi
Token pendaftaran yang sudah usang adalah token yang terkait dengan perangkat tidak aktif yang tidak terhubung ke FCM selama lebih dari sebulan. Seiring waktu, kemungkinan perangkat terhubung ke FCM lagi akan semakin menurun. Pengiriman pesan dan fanout topik untuk token usang ini kemungkinan tidak akan pernah dikirim.
Ada beberapa alasan mengapa token dapat menjadi usang. Misalnya, perangkat yang terkait dengan token hilang, hancur, atau dimasukkan ke dalam penyimpanan dan terlupakan.
Saat token yang sudah usang tidak aktif selama 270 hari, FCM akan menganggapnya sebagai token yang sudah tidak berlaku. Setelah masa berlaku token berakhir, FCM menandainya sebagai tidak valid dan menolak permintaan kirim ke alamat tersebut. Namun, FCM mengeluarkan token baru untuk instance aplikasi dalam kasus yang jarang terjadi ketika perangkat terhubung kembali dan aplikasi dibuka.
Praktik terbaik dasar
Ada beberapa praktik dasar yang harus Anda ikuti dalam aplikasi apa pun yang menggunakan FCM API untuk membuat permintaan kirim secara terprogram. Praktik terbaik utama adalah:
- Ambil token pendaftaran dari FCM dan simpan di server Anda. Peran penting server adalah memantau setiap token klien dan menyimpan daftar terbaru token aktif. Sebaiknya terapkan stempel waktu token dalam kode serta server Anda, dan update stempel waktu ini secara berkala.
- Pertahankan keaktualan token dan hapus token yang sudah tidak berlaku. Selain menghapus token yang tidak lagi dianggap valid oleh FCM, sebaiknya pantau indikator lain yang menandakan bahwa token telah menjadi usang dan menghapusnya secara proaktif. Panduan ini berisi pembahasan mengenai beberapa opsi yang Anda miliki untuk melakukannya.
Mengambil dan menyimpan token pendaftaran
Saat aplikasi dijalankan untuk pertama kalinya, FCM SDK akan menghasilkan token pendaftaran untuk instance aplikasi klien. Ini adalah token yang harus disertakan dalam permintaan kirim yang ditargetkan dari API, atau yang harus ditambahkan ke langganan topik untuk menarget topik.
Sebaiknya aplikasi Anda mengambil token ini saat pertama kali aplikasi dijalankan dan menyimpannya ke server aplikasi bersama stempel waktu. Stempel waktu ini harus diterapkan oleh kode dan server Anda, karena tidak disediakan oleh FCM SDK.
Selain itu, Anda harus menyimpan token ke server dan mengupdate stempel waktu setiap kali ada perubahan, seperti saat:
- Aplikasi dipulihkan di perangkat baru
- Pengguna meng-uninstal atau menginstal ulang aplikasi
- Pengguna menghapus data aplikasi
- Aplikasi menjadi aktif kembali setelah token yang ada untuk FCM tidak lagi tersedia.
Contoh: simpan token dan stempel waktu di Cloud Firestore
Misalnya, Anda dapat menggunakan Cloud Firestore untuk menyimpan token dalam koleksi
yang disebut fcmTokens
. Setiap ID dokumen dalam koleksi terkait dengan sebuah ID pengguna, dan dokumen menyimpan token pendaftaran saat ini beserta stempel waktunya yang terakhir diperbarui. Gunakan fungsi set
seperti yang ditunjukkan dalam contoh Kotlin ini:
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM registration token with any server-side account
* maintained by your application.
*
* @param token The new token.
*/
private fun sendTokenToServer(token: String?) {
// If you're running your own server, call API to send token and today's date for the user
// Example shown below with Firestore
// Add token and timestamp to Firestore for this user
val deviceToken = hashMapOf(
"token" to token,
"timestamp" to FieldValue.serverTimestamp(),
)
// Get user ID from Firebase Auth or your own server
Firebase.firestore.collection("fcmTokens").document("myuserid")
.set(deviceToken)
}
Setiap kali token diambil, token tersebut akan disimpan di Cloud Firestore dengan memanggil
sendTokenToServer
:
/**
* Called if the FCM registration token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the
* FCM registration token is initially generated so this is where you would retrieve the token.
*/
override fun onNewToken(token: String) {
Log.d(TAG, "Refreshed token: $token")
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// FCM registration token to your app server.
sendTokenToServer(token)
}
var token = Firebase.messaging.token.await()
// Check whether the retrieved token matches the one on your server for this user's device
val preferences = this.getPreferences(Context.MODE_PRIVATE)
val tokenStored = preferences.getString("deviceToken", "")
lifecycleScope.launch {
if (tokenStored == "" || tokenStored != token)
{
// If you have your own server, call API to send the above token and Date() for this user's device
// Example shown below with Firestore
// Add token and timestamp to Firestore for this user
val deviceToken = hashMapOf(
"token" to token,
"timestamp" to FieldValue.serverTimestamp(),
)
// Get user ID from Firebase Auth or your own server
Firebase.firestore.collection("fcmTokens").document("myuserid")
.set(deviceToken).await()
}
}
Mempertahankan keaktualan token dan menghapus token yang sudah tidak berlaku
Menentukan apakah sebuah token masih baru atau sudah usang tidak selalu mudah. Untuk mencakup semua kasus, Anda harus menerapkan batasan guna menentukan kapan token dianggap usang. Secara default, FCM menganggap token sudah usang jika instance aplikasinya belum terhubung selama sebulan. Token apa pun yang berusia lebih dari satu bulan kemungkinan merupakan perangkat yang tidak aktif. Perangkat yang aktif seharusnya telah memperbarui tokennya.
Tergantung pada kasus penggunaan Anda, satu bulan mungkin terlalu singkat atau terlalu lama, jadi terserah Anda untuk menentukan kriteria yang sesuai untuk Anda.
Mendeteksi respons token yang tidak valid dari backend FCM
Pastikan untuk mendeteksi respons token yang tidak valid dari FCM dan meresponsnya dengan menghapus token pendaftaran apa pun yang didapati tidak valid atau telah habis masa berlakunya dari sistem Anda. Dengan HTTP v1 API, pesan error ini dapat menunjukkan bahwa permintaan kirim Anda menarget token yang tidak valid atau sudah tidak berlaku lagi:
UNREGISTERED
(HTTP 404)INVALID_ARGUMENT
(HTTP 400)
Jika Anda yakin bahwa payload pesan valid dan Anda menerima salah satu respons tersebut untuk token yang ditarget, Anda dapat menghapus data token ini karena tidak akan valid lagi. Misalnya, untuk menghapus token yang tidak valid dari Cloud Firestore, Anda dapat men-deploy dan menjalankan fungsi seperti berikut:
// Registration token comes from the client FCM SDKs
const registrationToken = 'YOUR_REGISTRATION_TOKEN';
const message = {
data: {
// Information you want to send inside of notification
},
token: registrationToken
};
// Send message to device with provided registration token
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
})
.catch((error) => {
// Delete token for user if error code is UNREGISTERED or INVALID_ARGUMENT.
if (errorCode == "messaging/registration-token-not-registered") {
// If you're running your own server, call API to delete the
token for the user
// Example shown below with Firestore
// Get user ID from Firebase Auth or your own server
Firebase.firestore.collection("fcmTokens").document(user.uid).delete()
}
});
FCM hanya akan menampilkan respons token yang tidak valid jika masa berlaku token telah berakhir setelah 270 hari atau jika klien secara eksplisit membatalkan pendaftaran. Jika perlu melacak keusangan secara lebih akurat menurut definisi Anda sendiri, Anda dapat secara proaktif menghapus token pendaftaran yang sudah usang.
Mengupdate token secara rutin
Sebaiknya Anda mengambil dan mengupdate semua token pendaftaran di server Anda secara berkala. Hal ini mengharuskan Anda untuk:
- Menambahkan logika aplikasi di aplikasi klien untuk mengambil token saat ini menggunakan panggilan API yang sesuai (seperti
token(completion):
untuk platform Apple ataugetToken()
untuk Android), lalu mengirimkan token saat ini ke server aplikasi Anda untuk disimpan (dengan stempel waktu). Tugas ini dapat dilakukan per bulan, dan dikonfigurasi untuk mencakup semua klien atau token. - Menambahkan logika server untuk mengupdate stempel waktu token secara berkala, terlepas dari apakah token telah berubah atau belum.
Untuk contoh logika Android dalam mengupdate token menggunakan WorkManager, lihat Mengelola Token Cloud Messaging di blog Firebase.
Apa pun pola pengaturan waktu yang Anda ikuti, pastikan untuk mengupdate token secara berkala. Frekuensi update satu kali per bulan akan menghasilkan keseimbangan antara dampak terhadap baterai dan pendeteksian token pendaftaran yang tidak aktif. Dengan melakukan update ini, Anda juga memastikan bahwa perangkat yang tidak aktif akan me-refresh pendaftarannya saat perangkat kembali aktif. Tidak ada gunanya melakukan refresh lebih dari seminggu sekali.
Menghapus token pendaftaran yang sudah tidak berlaku
Sebelum mengirim pesan ke perangkat, pastikan stempel waktu token pendaftaran perangkat berada dalam periode tenggang ketidakberlakuan. Misalnya, Anda dapat menerapkan Cloud Functions for Firebase untuk menjalankan pemeriksaan harian guna memastikan bahwa stempel waktu berada dalam periode tenggang ketidakberlakuan, seperti const
EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;
, lalu menghapus token yang sudah usang:
exports.pruneTokens = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
// Get all documents where the timestamp exceeds is not within the past month
const staleTokensResult = await admin.firestore().collection('fcmTokens')
.where("timestamp", "<", Date.now() - EXPIRATION_TIME)
.get();
// Delete devices with stale tokens
staleTokensResult.forEach(function(doc) { doc.ref.delete(); });
});
Menghentikan langganan token usang pada topik
Jika menggunakan topik, Anda juga dapat membatalkan pendaftaran token usang dari topik langganannya. Hal ini melibatkan dua langkah:
- Aplikasi Anda harus kembali berlangganan topik sebulan sekali dan setiap kali token pendaftaran berubah. Ini akan membentuk solusi pemulihan diri, ketika langganan muncul kembali secara otomatis saat aplikasi kembali aktif.
- Jika instance aplikasi tidak aktif selama satu bulan (atau periode keusangan yang Anda tentukan sendiri), Anda harus menghentikan langganannya dari topik menggunakan Firebase Admin SDK untuk menghapus pemetaan token ke topik dari backend FCM.
Dua langkah ini bermanfaat mempercepat fanout karena jumlah token usang yang harus di-fanout menjadi lebih sedikit, dan instance aplikasi yang usang akan berlangganan kembali secara otomatis setelah aktif lagi.
Mengukur keberhasilan pengiriman
Untuk mendapatkan gambaran pengiriman pesan yang paling akurat, sebaiknya hanya kirim pesan ke instance aplikasi yang digunakan secara aktif. Hal ini sangat penting jika Anda rutin mengirim pesan ke topik dengan jumlah pelanggan yang besar. Jika sebagian pelanggan tersebut sebenarnya tidak aktif, dampaknya pada statistik pengiriman Anda dapat menjadi signifikan dari waktu ke waktu.
Sebelum menargetkan pesan ke token, pertimbangkan:
- Apakah Google Analytics, data yang diambil di BigQuery, atau sinyal pelacakan lainnya menunjukkan bahwa token aktif?
- Apakah upaya pengiriman sebelumnya gagal secara konsisten selama jangka waktu tertentu?
- Apakah token pendaftaran telah diupdate di server Anda dalam sebulan terakhir?
- Untuk perangkat Android, apakah FCM Data API melaporkan persentase kegagalan pengiriman pesan yang tinggi karena
droppedDeviceInactive
?
Untuk mendapatkan informasi lebih lanjut tentang pengiriman, baca artikel Memahami pengiriman pesan.