หากคุณใช้ FCM API เพื่อสร้างคำขอส่งแบบเป็นโปรแกรม คุณอาจ พบว่าเมื่อเวลาผ่านไป คุณกำลังสิ้นเปลืองทรัพยากรโดยการส่งข้อความไปยังอุปกรณ์ที่ไม่ได้ใช้งาน ซึ่งมีโทเค็นการลงทะเบียนที่ล้าสมัย สถานการณ์นี้อาจส่งผลต่อข้อมูลการส่งข้อความที่รายงานในคอนโซล Firebase หรือข้อมูลที่ส่งออกไปยัง BigQuery โดยแสดงเป็นการลดลงอย่างมาก (แต่ไม่ถูกต้องจริง) ของอัตราการส่ง คู่มือนี้จะกล่าวถึงมาตรการบางอย่างที่คุณสามารถทำได้เพื่อช่วยให้มั่นใจว่าการกำหนดเป้าหมายข้อความมีประสิทธิภาพและการรายงานการส่งถูกต้อง
โทเค็นการลงทะเบียนที่ล้าสมัยและหมดอายุ
โทเค็นการลงทะเบียนที่ล้าสมัยคือโทเค็นที่เชื่อมโยงกับอุปกรณ์ที่ไม่ได้ใช้งานซึ่งไม่ได้เชื่อมต่อกับ FCM มานานกว่า 1 เดือน เมื่อเวลาผ่านไป โอกาสที่อุปกรณ์จะเชื่อมต่อกับ FCM อีกครั้งจะลดลงเรื่อยๆ การส่งข้อความและการกระจายข้อความไปยังหัวข้อสำหรับโทเค็นที่ล้าสมัยเหล่านี้มีแนวโน้มที่จะไม่ได้รับการส่ง
มีหลายสาเหตุที่ทำให้โทเค็นล้าสมัย เช่น อุปกรณ์ที่เชื่อมโยงกับโทเค็นอาจสูญหาย ถูกทำลาย หรือถูกเก็บไว้และลืมไป
สำหรับ Android เมื่อโทเค็นที่ล้าสมัยไม่มีการใช้งานครบ 270 วัน FCM จะถือว่าโทเค็นเหล่านั้นหมดอายุ เมื่อโทเค็นหมดอายุ FCM จะทำเครื่องหมายว่าโทเค็นไม่ถูกต้องและปฏิเสธการส่งไปยังโทเค็นดังกล่าว อย่างไรก็ตาม FCM จะออกโทเค็นใหม่สำหรับอินสแตนซ์ของแอปในกรณีที่ อุปกรณ์เชื่อมต่ออีกครั้งและมีการเปิดแอป ซึ่งเกิดขึ้นไม่บ่อยนัก
สำหรับแพลตฟอร์มอื่นๆ เช่น iOS, FCM จะใช้บริการ Push ที่เกี่ยวข้อง (เช่น APNs) ซึ่งไม่มีการหมดอายุของโทเค็นตามการไม่มีการใช้งาน 270 วันแบบเดียวกัน ดังนั้นเราขอแนะนำให้คุณรักษาความสดใหม่ของโทเค็นและนำโทเค็นการลงทะเบียนที่ล้าสมัยออก
แนวทางปฏิบัติแนะนำเบื้องต้น
มีแนวทางปฏิบัติพื้นฐานบางอย่างที่คุณควรปฏิบัติตามในแอปใดก็ตามที่ใช้ FCM API เพื่อสร้างคำขอส่งแบบเป็นโปรแกรม แนวทางปฏิบัติแนะนำหลักๆ มีดังนี้
- ดึงข้อมูลโทเค็นการลงทะเบียนจาก FCM และจัดเก็บไว้ใน เซิร์ฟเวอร์ บทบาทสำคัญของเซิร์ฟเวอร์คือการติดตามโทเค็นของไคลเอ็นต์แต่ละรายและเก็บรักษารายการโทเค็นที่ใช้งานอยู่ให้เป็นปัจจุบัน เราขอแนะนำอย่างยิ่งให้ใช้การประทับเวลาโทเค็นในโค้ดและเซิร์ฟเวอร์ของคุณ และอัปเดตการประทับเวลานี้เป็นระยะๆ
- รักษาความสดใหม่ของโทเค็นและนำโทเค็นที่ล้าสมัยออก นอกเหนือจาก การนำโทเค็นที่ FCM ไม่ถือว่าถูกต้องอีกต่อไปออกแล้ว คุณอาจต้องการ ตรวจสอบสัญญาณอื่นๆ ที่บ่งบอกว่าโทเค็นล้าสมัยและนำโทเค็นเหล่านั้นออก อย่างรวดเร็ว คู่มือนี้จะกล่าวถึงตัวเลือกบางอย่างในการดำเนินการดังกล่าว
ดึงและจัดเก็บโทเค็นการลงทะเบียน
เมื่อเริ่มต้นแอปเป็นครั้งแรก FCM SDK จะสร้างโทเค็นการลงทะเบียน สำหรับอินสแตนซ์ของแอปไคลเอ็นต์ ซึ่งเป็นโทเค็นที่คุณต้องรวมไว้ในคำขอส่งที่กำหนดเป้าหมายจาก API หรือเพิ่มลงในการสมัครใช้บริการหัวข้อเพื่อกำหนดเป้าหมายหัวข้อ
เราขอแนะนำอย่างยิ่งให้แอปดึงข้อมูลโทเค็นนี้เมื่อเริ่มต้นเป็นครั้งแรกและบันทึกลงในเซิร์ฟเวอร์ของแอปพร้อมกับการประทับเวลา คุณต้องใช้การประทับเวลานี้ในโค้ดและเซิร์ฟเวอร์ เนื่องจาก ไม่ได้ให้การประทับเวลานี้แก่คุณ FCM
นอกจากนี้ คุณควรบันทึกโทเค็นลงในเซิร์ฟเวอร์และอัปเดตการประทับเวลาทุกครั้งที่โทเค็นมีการเปลี่ยนแปลง เช่น ในกรณีต่อไปนี้
- มีการกู้คืนแอปในอุปกรณ์ใหม่
- ผู้ใช้ถอนการติดตั้งหรือติดตั้งแอปอีกครั้ง
- ผู้ใช้ล้างข้อมูลแอป
- แอปกลับมาใช้งานได้อีกครั้งหลังจาก FCM หมดอายุโทเค็นที่มีอยู่
ตัวอย่าง: จัดเก็บโทเค็นและการประทับเวลาใน Cloud Firestore
ตัวอย่างเช่น คุณสามารถใช้ Cloud Firestore เพื่อจัดเก็บโทเค็นในคอลเล็กชัน
ที่ชื่อว่า fcmTokens รหัสเอกสารแต่ละรายการในคอลเล็กชันจะสอดคล้องกับรหัสผู้ใช้ และเอกสารจะจัดเก็บโทเค็นการลงทะเบียนปัจจุบันและการประทับเวลาที่อัปเดตล่าสุด ใช้ฟังก์ชัน set ตามที่แสดงในตัวอย่าง Kotlin นี้
/**
* 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)
}
เมื่อใดก็ตามที่มีการดึงข้อมูลโทเค็น ระบบจะจัดเก็บโทเค็นไว้ใน Cloud Firestore โดยการเรียก
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()
}
}
รักษาความสดใหม่ของโทเค็นและนำโทเค็นที่ล้าสมัยออก
การพิจารณาว่าโทเค็นสดใหม่หรือล้าสมัยนั้นไม่ใช่เรื่องง่ายเสมอไป คุณควรใช้เกณฑ์กำหนดว่าเมื่อใดที่ถือว่าโทเค็นล้าสมัย โดยค่าเริ่มต้น FCM จะถือว่าโทเค็นล้าสมัยหากอินสแตนซ์ของแอป ไม่ได้เชื่อมต่อมาเป็นเวลา 1 เดือน โทเค็นที่เก่ากว่า 1 เดือนมีแนวโน้มที่จะเป็นอุปกรณ์ที่ไม่ได้ใช้งาน เนื่องจากอุปกรณ์ที่ใช้งานอยู่จะรีเฟรชโทเค็น
ระยะเวลา 1 เดือนอาจสั้นหรือยาวเกินไป ทั้งนี้ขึ้นอยู่กับกรณีการใช้งาน ดังนั้นคุณจึงต้องกำหนดเกณฑ์ที่เหมาะกับคุณ
ตรวจหาการตอบกลับโทเค็นที่ไม่ถูกต้องจากแบ็กเอนด์ของ FCM
ตรวจสอบว่าได้ตรวจหาการตอบกลับโทเค็นที่ไม่ถูกต้องจาก FCM และตอบสนองด้วย การลบโทเค็นการลงทะเบียนที่ไม่ถูกต้อง หรือหมดอายุออกจากระบบ สำหรับ HTTP v1 API ข้อความแสดงข้อผิดพลาดเหล่านี้อาจบ่งบอกว่าคำขอส่งของคุณกำหนดเป้าหมายโทเค็นที่ไม่ถูกต้องหรือหมดอายุ
UNREGISTERED(HTTP 404)INVALID_ARGUMENT(HTTP 400)
หากคุณมั่นใจว่าเพย์โหลดของข้อความถูกต้องและได้รับคำตอบใดคำตอบหนึ่งต่อไปนี้สำหรับโทเค็นที่กำหนดเป้าหมาย คุณสามารถลบบันทึกโทเค็นนี้ได้อย่างปลอดภัย เนื่องจากโทเค็นนี้จะไม่มีวันถูกต้องอีกต่อไป ตัวอย่างเช่น หากต้องการลบโทเค็นที่ไม่ถูกต้อง ออกจาก Cloud Firestore คุณสามารถติดตั้งใช้งานและเรียกใช้ฟังก์ชันต่อไปนี้
// 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 (error.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 จะแสดงการตอบกลับโทเค็นที่ไม่ถูกต้องหากโทเค็นสำหรับอุปกรณ์ Android หมดอายุหลังจากไม่มีการใช้งาน 270 วัน หรือหากไคลเอ็นต์ยกเลิกการลงทะเบียน อย่างชัดแจ้ง หากต้องการติดตามความล้าสมัยอย่างแม่นยำมากขึ้นตามคำจำกัดความของคุณเอง คุณสามารถนำโทเค็นการลงทะเบียนที่ล้าสมัยออกอย่างรวดเร็ว
อัปเดตโทเค็นเป็นประจำ
เราขอแนะนำให้คุณดึงและอัปเดตโทเค็นการลงทะเบียนทั้งหมดในเซิร์ฟเวอร์เป็นระยะๆ ซึ่งคุณต้องดำเนินการต่อไปนี้
- เพิ่มตรรกะของแอปในแอปไคลเอ็นต์เพื่อดึงข้อมูลโทเค็นปัจจุบันโดยใช้การ
เรียก API ที่เหมาะสม (เช่น
token(completion):สำหรับแพลตฟอร์ม Apple หรือgetToken()สำหรับ Android) จากนั้นส่งโทเค็นปัจจุบันไปยังเซิร์ฟเวอร์ของแอปเพื่อจัดเก็บ (พร้อมการประทับเวลา) ซึ่งอาจเป็นงานรายเดือนที่กำหนดค่าให้ครอบคลุมไคลเอ็นต์หรือโทเค็นทั้งหมด - เพิ่มตรรกะของเซิร์ฟเวอร์เพื่ออัปเดตการประทับเวลาของโทเค็นเป็นระยะๆ ไม่ว่าโทเค็นจะมีการเปลี่ยนแปลงหรือไม่ก็ตาม
ดูตัวอย่างตรรกะของ Android สำหรับการอัปเดตโทเค็นโดยใช้ WorkManager, ได้ที่ การจัดการโทเค็น Cloud Messaging ในบล็อก Firebase
ไม่ว่าคุณจะใช้รูปแบบการกำหนดเวลาแบบใดก็ตาม โปรดอัปเดตโทเค็นเป็นระยะๆ ความถี่ในการอัปเดตเดือนละครั้งจะสร้างสมดุลที่ดีระหว่างผลกระทบต่อแบตเตอรี่และการตรวจหาโทเค็นการลงทะเบียนที่ไม่ได้ใช้งาน การรีเฟรชนี้ยังช่วยให้มั่นใจได้ว่าอุปกรณ์ที่ไม่ได้ใช้งานจะรีเฟรชการลงทะเบียนเมื่อกลับมาใช้งานได้อีกครั้ง การรีเฟรชบ่อยกว่าสัปดาห์ละครั้งไม่มีประโยชน์
นำโทเค็นการลงทะเบียนที่ไม่มีอัปเดตออก
ก่อนส่งข้อความไปยังอุปกรณ์ ให้ตรวจสอบว่าการประทับเวลาของโทเค็นการลงทะเบียนของอุปกรณ์อยู่ในช่วงระยะเวลาที่ถือว่าล้าสมัย ตัวอย่างเช่น คุณ
สามารถใช้ Cloud Functions for Firebase เพื่อเรียกใช้การตรวจสอบรายวันเพื่อให้แน่ใจว่าการ
ประทับเวลาอยู่ในช่วงระยะเวลาที่ถือว่าล้าสมัยที่กำหนดไว้ เช่น const
EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; จากนั้นนำโทเค็นที่ล้าสมัยออก
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(); });
});
ยกเลิกการสมัครใช้บริการหัวข้อของโทเค็นที่ล้าสมัย
หากใช้หัวข้อ คุณอาจต้องการยกเลิกการลงทะเบียนโทเค็นที่ล้าสมัยจากหัวข้อที่โทเค็นเหล่านั้นสมัครใช้บริการอยู่ ซึ่งมี 2 ขั้นตอนดังนี้
- แอปควรสมัครใช้บริการหัวข้ออีกครั้งเดือนละครั้งและทุกครั้งที่โทเค็นการลงทะเบียนมีการเปลี่ยนแปลง ซึ่งจะเป็นโซลูชันการแก้ไขตัวเอง โดยการสมัครใช้บริการจะปรากฏขึ้นอีกครั้งโดยอัตโนมัติเมื่อแอปกลับมาใช้งานได้อีกครั้ง
- หากอินสแตนซ์ของแอปไม่มีการใช้งานเป็นเวลา 1 เดือน (หรือช่วงระยะเวลาที่ถือว่าไม่มีอัปเดตของคุณเอง) คุณควรยกเลิกการสมัครใช้บริการหัวข้อโดยใช้ Firebase Admin SDK เพื่อลบการแมปโทเค็นกับหัวข้อออกจากแบ็กเอนด์FCM
ประโยชน์ของ 2 ขั้นตอนนี้คือการกระจายข้อความไปยังหัวข้อจะเกิดขึ้นเร็วขึ้นเนื่องจากมีโทเค็นที่ล้าสมัยน้อยลง และอินสแตนซ์ของแอปที่ล้าสมัยจะสมัครใช้บริการอีกครั้งโดยอัตโนมัติเมื่อกลับมาใช้งานได้อีกครั้ง
วัดความสำเร็จในการส่ง
วิธีที่ดีที่สุดในการดูภาพรวมที่แม่นยำที่สุดของการส่งข้อความคือการส่งข้อความไปยังอินสแตนซ์ของแอปที่ใช้งานอยู่เท่านั้น ซึ่งมีความสำคัญอย่างยิ่งหากคุณส่งข้อความไปยังหัวข้อที่มีผู้ติดตามจำนวนมากเป็นประจำ หากผู้ติดตามบางส่วนไม่ได้ใช้งานจริง ผลกระทบต่อสถิติการส่งอาจมีนัยสำคัญเมื่อเวลาผ่านไป
ก่อนกำหนดเป้าหมายข้อความไปยังโทเค็น ให้พิจารณาสิ่งต่อไปนี้
- Google Analytics, ข้อมูลที่บันทึกไว้ใน BigQuery หรือสัญญาณการติดตามอื่นๆ บ่งบอกว่าโทเค็นใช้งานอยู่หรือไม่
- การพยายามส่งครั้งก่อนๆ ล้มเหลวอย่างต่อเนื่องในช่วงระยะเวลาหนึ่งหรือไม่
- โทเค็นการลงทะเบียนได้รับการอัปเดตในเซิร์ฟเวอร์ของคุณในช่วงเดือนที่ผ่านมาหรือไม่
- สำหรับอุปกรณ์ Android, FCM Data API
รายงานว่าการส่งข้อความล้มเหลวเป็นเปอร์เซ็นต์สูงเนื่องจาก
droppedDeviceInactiveหรือไม่
ดูข้อมูลเพิ่มเติมเกี่ยวกับการส่งได้ที่ ทำความเข้าใจการส่งข้อความ