แนวทางปฏิบัติแนะนำสำหรับการจัดการการลงทะเบียน FCM

หากคุณใช้ FCM API เพื่อสร้างคำขอส่งแบบเป็นโปรแกรม คุณอาจ พบว่าเมื่อเวลาผ่านไป คุณกำลังสิ้นเปลืองทรัพยากรโดยการส่งข้อความไปยังอุปกรณ์ที่ไม่ได้ใช้งานซึ่งมีการลงทะเบียนที่ล้าสมัย สถานการณ์นี้อาจส่งผลต่อข้อมูลการส่งข้อความ ที่รายงานในคอนโซล Firebase หรือข้อมูลที่ส่งออกไปยัง BigQuery, โดยแสดงเป็นอัตราการส่งที่ลดลงอย่างมาก (แต่ไม่ถูกต้อง) คู่มือนี้จะกล่าวถึงมาตรการบางอย่างที่คุณสามารถทำได้เพื่อช่วยให้กำหนดเป้าหมายข้อความได้อย่างมีประสิทธิภาพและรายงานการส่งที่ถูกต้อง

การลงทะเบียนที่ล้าสมัยและหมดอายุ

การลงทะเบียนที่ล้าสมัยจะเชื่อมโยงกับอุปกรณ์ที่ไม่ได้ใช้งานซึ่งไม่ได้เชื่อมต่อ กับ FCM มานานกว่า 1 เดือน เมื่อเวลาผ่านไป อุปกรณ์จะเชื่อมต่อกับ FCM อีกครั้งได้ยากขึ้นเรื่อยๆ การส่งข้อความและการกระจายข้อความไปยังหัวข้อสำหรับการลงทะเบียนที่ล้าสมัยเหล่านี้มีแนวโน้มที่จะไม่ได้รับการส่ง

การลงทะเบียนอาจล้าสมัยได้ด้วยเหตุผลหลายประการ เช่น อุปกรณ์ที่เชื่อมโยงกับการลงทะเบียนอาจสูญหาย เสียหาย หรือถูกเก็บไว้และลืมไปแล้ว

สำหรับ Android เมื่อการลงทะเบียนไม่ได้ใช้งานเป็นเวลา 270 วัน FCM จะถือว่าหมดอายุ และลบออก เมื่อการลงทะเบียนหมดอายุแล้ว FCM จะทำเครื่องหมายว่าการลงทะเบียนนั้นไม่ถูกต้องและปฏิเสธการส่งไปยังการลงทะเบียนดังกล่าว โปรดทราบว่า Firebase Installation ID (FID) เองได้รับการจัดการโดย บริการ Firebase Installations (FIS) ไม่ใช่โดย FCM ในกรณีที่เกิดขึ้นได้ยากที่อุปกรณ์จะเชื่อมต่ออีกครั้งและมีการเปิดแอปหลังจากที่ระบบลบการลงทะเบียน ออกไปแล้ว แอปไคลเอ็นต์จะลงทะเบียนกับ FCM อีกครั้งโดยใช้ FID ที่ดึงข้อมูลจาก FIS โปรดทราบว่า FID อาจมีการเปลี่ยนแปลง ดูจัดการการติดตั้งใช้งาน Firebaseสำหรับ รายละเอียดเกี่ยวกับเวลาที่ออก FID ใหม่

สำหรับแพลตฟอร์มอื่นๆ เช่น iOS, FCM จะอาศัยบริการ Push ที่เกี่ยวข้อง (เช่น APNs) ซึ่งไม่มีการหมดอายุตามการไม่ได้ใช้งาน 270 วันแบบเดียวกัน เราขอแนะนำให้คุณรักษาการลงทะเบียนให้เป็นปัจจุบันและนำการลงทะเบียนที่ล้าสมัยออก

แนวทางปฏิบัติแนะนำเบื้องต้น

มีแนวทางปฏิบัติพื้นฐานบางอย่างที่คุณควรปฏิบัติตามในแอปใดก็ตามที่ใช้ FCM API เพื่อสร้างคำขอส่งแบบเป็นโปรแกรม แนวทางปฏิบัติแนะนำหลักมีดังนี้

  • ดึงข้อมูล Firebase Installation ID (FID) จาก FCM และจัดเก็บไว้ในเซิร์ฟเวอร์ของแอป บทบาทที่สำคัญของเซิร์ฟเวอร์คือการติดตาม FID ที่ลงทะเบียนของไคลเอ็นต์แต่ละรายและเก็บรายการ FID ที่ใช้งานอยู่ให้เป็นปัจจุบัน เราขอแนะนำอย่างยิ่งให้ใช้การประทับเวลาการลงทะเบียนในฐานข้อมูลและอัปเดตทุกครั้งที่มีการอัปโหลดการลงทะเบียน
  • รักษาการลงทะเบียนให้เป็นปัจจุบันและนำการลงทะเบียนที่ล้าสมัยออก นอกเหนือจากการนำการลงทะเบียนที่ FCM ไม่ถือว่าถูกต้องอีกต่อไปออกแล้ว คุณอาจต้องการตรวจสอบสัญญาณอื่นๆ ที่บ่งบอกว่าการลงทะเบียนล้าสมัยและนำการลงทะเบียนเหล่านั้นออกก่อน คู่มือนี้จะกล่าวถึงตัวเลือกบางอย่างที่คุณสามารถทำได้

ดึงข้อมูลและจัดเก็บ Firebase Installation ID

เมื่อเริ่มต้นแอปครั้งแรก FCM SDK จะลงทะเบียนอินสแตนซ์ของแอป กับ FCM และแสดง Firebase Installation ID (FID) ซึ่งเป็นตัวระบุที่คุณต้องใส่ไว้ในคำขอส่งที่กำหนดเป้าหมายจาก API หรือใช้สำหรับการสมัครใช้บริการหัวข้อ

เราขอแนะนำอย่างยิ่งให้บันทึก FID ลงในเซิร์ฟเวอร์ของแอปพร้อมกับการประทับเวลาทุกครั้งที่มีการอัปโหลด การอัปเดตการประทับเวลาในคำขออัปโหลดทุกครั้งจะช่วยให้เซิร์ฟเวอร์ ทราบว่ามีการเปิดอินสแตนซ์ของแอปและซิงค์สำเร็จ กับแบ็กเอนด์ FCM ครั้งล่าสุดเมื่อใด

คุณควรจัดการการลงทะเบียนและการอัปเดตดังนี้ โดยขึ้นอยู่กับว่าได้เปิดใช้หรือปิดใช้การเริ่มต้นใช้งานอัตโนมัติ (รวมถึงกรณีที่ไม่รองรับ)

  • (แนะนำ) เมื่อเปิดใช้การเริ่มต้นใช้งานอัตโนมัติ: SDK จะรักษาการลงทะเบียนให้เป็นปัจจุบันและตรวจสอบการเปลี่ยนแปลงโดยอัตโนมัติ ระบบจะเรียกใช้การเรียกกลับ onRegistered() เป็นประจำในการซิงค์ตามปกติระหว่างการเริ่มต้นแอป รวมถึงเมื่อมีการเปลี่ยนแปลง FID เพียงแค่ใช้การเรียกกลับนี้เพื่ออัปโหลด FID ไปยังเซิร์ฟเวอร์และบันทึกการประทับเวลาปัจจุบัน
  • เมื่อปิดใช้การเริ่มต้นใช้งานอัตโนมัติ: ระบบจะไม่เรียกใช้การเรียกกลับ onRegistered() โดยอัตโนมัติเมื่อเริ่มต้น หากต้องการติดตามการลงทะเบียนและ รักษาการลงทะเบียนให้เป็นปัจจุบัน ให้เรียกใช้ register() เมื่อเริ่มต้นแอป เช่น ใน Android ให้เรียกใช้ใน onCreate()ของกิจกรรมหลัก การเรียกใช้ที่สำเร็จจะทริกเกอร์กระบวนการลงทะเบียนFCMโดยใช้ FID และส่ง FID ไปยังการเรียกกลับ onRegistered() ซึ่งจะช่วยให้แอปอัปโหลด FID และอัปเดตการประทับเวลาในเซิร์ฟเวอร์ได้

ตัวอย่าง: จัดเก็บ FID และการประทับเวลาใน Cloud Firestore

ตัวอย่างเช่น คุณสามารถใช้ Cloud Firestore เพื่อจัดเก็บ FID ในคอลเล็กชันที่ชื่อว่า fcmRegistrations รหัสเอกสารแต่ละรายการในคอลเล็กชันจะสอดคล้องกับรหัสผู้ใช้ และเอกสารจะจัดเก็บ FID ปัจจุบันและการประทับเวลาที่อัปเดตล่าสุด ใช้ฟังก์ชัน set ตามที่แสดงในตัวอย่าง Kotlin นี้

private fun sendRegistrationToServer(installationId: String?) {
    // If you're running your own server, call API to send registration details and today's date for the user

    // Example shown uses Firestore
    // Add FID and timestamp to Firestore for this user
    val deviceFid = hashMapOf(
        "installationId" to installationId,
        "timestamp" to FieldValue.serverTimestamp(),
    )
    // Get user ID from Firebase Auth or your own server
    Firebase.firestore.collection("fcmRegistrations").document("myuserid")
        .set(deviceFid)
}

ระบบจะเรียกใช้การเรียกกลับทุกครั้งที่ลงทะเบียนหรืออัปเดต Firebase Installation ID สำเร็จ onRegistered() คุณควรใช้การเรียกกลับนี้เพื่ออัปโหลด FID และอัปเดตการประทับเวลา

override fun onRegistered(installationId: String) {
    Log.d(TAG, "Registered installation ID: $installationId")

    // Send the Firebase Installation ID (FID) to your app server. Your app
    // server should save the FID and update the timestamp upon receipt.
    sendRegistrationToServer(installationId)
}

สำหรับอินสแตนซ์ที่ปิดใช้การเริ่มต้นใช้งานอัตโนมัติ ให้เรียกใช้ register() เมื่อเริ่มต้นแอป (เช่น ใน onCreate()) เพื่อทริกเกอร์โฟลว์การลงทะเบียนและการส่ง FID ผ่าน onRegistered():

// Trigger manual registration if auto-initialization is turned off.
FirebaseMessaging.getInstance().register()
    .addOnCompleteListener(this) { task ->
        if (task.isSuccessful) {
            // The registration callback onRegistered() will be invoked with the current FID.
        } else {
            Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception)
        }
    }

รักษาการลงทะเบียนให้เป็นปัจจุบันและนำการลงทะเบียนที่ล้าสมัยออก

การพิจารณาว่าการลงทะเบียนเป็นปัจจุบันหรือล้าสมัยนั้นไม่ใช่เรื่องง่ายเสมอไป คุณควรกำหนดเกณฑ์ว่าเมื่อใดที่ถือว่าการลงทะเบียนล้าสมัย เพื่อให้ครอบคลุมทุกกรณี โดยค่าเริ่มต้น FCM จะถือว่าการลงทะเบียน ล้าสมัยหากอินสแตนซ์ของแอปไม่ได้เชื่อมต่อมาเป็นเวลา 1 เดือน การลงทะเบียนที่เก่ากว่า 1 เดือนมีแนวโน้มที่จะเป็นอุปกรณ์ที่ไม่ได้ใช้งาน เนื่องจากอุปกรณ์ที่ใช้งานอยู่จะรีเฟรชการลงทะเบียน

ระยะเวลา 1 เดือนอาจสั้นหรือยาวเกินไป ทั้งนี้ขึ้นอยู่กับกรณีการใช้งาน คุณจึงต้องกำหนดเกณฑ์ที่เหมาะกับคุณ

ตรวจหาการตอบกลับที่ไม่ถูกต้องจากแบ็กเอนด์ของ FCM

ตรวจสอบว่าได้ตรวจหาคำตอบที่เป็นโมฆะจาก FCM และตอบกลับโดยการลบ การลงทะเบียนที่ทราบว่าไม่ถูกต้องหรือหมดอายุออกจากระบบ สำหรับ HTTP v1 API ข้อความแสดงข้อผิดพลาดเหล่านี้อาจบ่งบอกว่าคำขอส่งของคุณกำหนดเป้าหมายการลงทะเบียนที่ไม่ถูกต้องหรือหมดอายุ

  • UNREGISTERED (HTTP 404)
  • INVALID_ARGUMENT (HTTP 400)

หากคุณมั่นใจว่าเพย์โหลดของข้อความถูกต้องและได้รับการตอบกลับใดรายการหนึ่งนี้สำหรับการลงทะเบียนที่กำหนดเป้าหมาย คุณสามารถลบบันทึกการลงทะเบียนนี้ได้อย่างปลอดภัย เนื่องจากจะไม่ถูกต้องอีกต่อไป ตัวอย่างเช่น หากต้องการลบ การลงทะเบียนที่ไม่ถูกต้องออกจาก Cloud Firestore คุณสามารถติดตั้งใช้งานและเรียกใช้ฟังก์ชัน ต่อไปนี้

        // Firebase Installation ID comes from the client FCM SDKs
        const firebaseInstallationId = 'YOUR_FIREBASE_INSTALLATION_ID';

        const message = {
            data: {
                // Information you want to send inside of notification
            },
            fid: firebaseInstallationId
        };

        // Send message to device with provided Firebase Installation ID
        getMessaging().send(message)
        .then((response) => {
            // Response is a message ID string.
        })
        .catch((error) => {
            // Delete registration 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 registration for the user
                // Example shown uses Firestore
                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmRegistrations").document(user.uid).delete()
            }
        });

FCM จะแสดงการตอบกลับที่ไม่ถูกต้องหากการลงทะเบียนสำหรับอุปกรณ์ Android หมดอายุหลังจากไม่ได้ใช้งานเป็นเวลา 270 วัน หรือหากไคลเอ็นต์ยกเลิกการลงทะเบียนอย่างชัดแจ้ง หากต้องการติดตามการล้าสมัยอย่างแม่นยำมากขึ้นตามคำจำกัดความของคุณ เอง คุณสามารถนำการลงทะเบียนที่ล้าสมัยออกก่อนได้

อัปเดตการลงทะเบียนเป็นประจำ

ไม่ว่าการลงทะเบียนจะอิงตาม FID หรือโทเค็นการลงทะเบียนเดิม เซิร์ฟเวอร์ควรจะอัปเดตการประทับเวลาการลงทะเบียนในฐานข้อมูลทุกครั้งที่มีการส่งคำขออัปโหลด การประทับเวลานี้ทำหน้าที่เป็นสัญญาณสำหรับ การติดตั้งแอป ซึ่งจะแจ้งให้ไคลเอ็นต์ทราบว่าได้เปิดแอปและ ซิงค์กับแบ็กเอนด์ของ FCM สำเร็จแล้ว ใช้กลยุทธ์ที่เหมาะสมโดยขึ้นอยู่กับ API ที่คุณใช้

สำหรับแอปไคลเอ็นต์ที่ใช้ FID API คุณไม่ จำเป็นต้องกำหนดเวลาให้งานเบื้องหลังทำงานเป็นระยะๆ ในแอปไคลเอ็นต์เพื่อดึงข้อมูลหรือรีเฟรชการลงทะเบียน SDK จะจัดการการรีเฟรชภายใต้การเริ่มต้นใช้งานอัตโนมัติโดยอัตโนมัติ และส่ง FID ปัจจุบันที่ถูกต้องไปยังการเรียกกลับ onRegistered() เป็นประจำในการซิงค์ตามปกติระหว่างการเริ่มต้นแอป

หากต้องการให้เซิร์ฟเวอร์เป็นปัจจุบัน ให้ใช้กลยุทธ์การอัปโหลดเมื่อเริ่มต้นที่ระบุไว้ใน ดึงข้อมูลและจัดเก็บ Firebase Installation ID:

  • เปิดใช้การเริ่มต้นใช้งานอัตโนมัติ: SDK จะตรวจสอบว่าได้ส่ง FID ล่าสุดไปยังเซิร์ฟเวอร์ในการซิงค์ตามปกติระหว่างการเริ่มต้นแอป
  • ปิดใช้การเริ่มต้นใช้งานอัตโนมัติหรือไม่รองรับ: เรียกใช้ register() เมื่อเริ่มต้นแอป (เช่น ใน Android ให้เรียกใช้ใน onCreate()) ของกิจกรรมหลัก) เพื่อบังคับลำดับการลงทะเบียนและทริกเกอร์การส่ง FID ไปยัง การเรียกกลับ onRegistered() ของคุณ

กลยุทธ์เหล่านี้รับประกันว่าเซิร์ฟเวอร์จะมี FID ที่ใช้งานอยู่ล่าสุดเสมอ และสามารถกู้คืนจากการอัปโหลดที่ไม่สำเร็จได้โดยอัตโนมัติ ซึ่งจะทำให้แอปพลิเคชันมีความยืดหยุ่นสูง

API โทเค็นการลงทะเบียนที่เลิกใช้งานแล้ว

หากคุณใช้โทเค็นการลงทะเบียนเดิม ไคลเอ็นต์ SDK จะไม่จัดการการรีเฟรชในการซิงค์ตามปกติโดยอัตโนมัติ ดังนั้น เราขอแนะนำให้คุณดึงข้อมูลและอัปเดตโทเค็นการลงทะเบียนทั้งหมดในเซิร์ฟเวอร์เป็นระยะๆ ซึ่งคุณต้องทำดังนี้

  • เพิ่มตรรกะของแอปในแอปไคลเอ็นต์เพื่อดึงข้อมูลโทเค็นปัจจุบันโดยใช้การ เรียก API ที่เหมาะสม (เช่น token(completion): สำหรับแพลตฟอร์ม Apple หรือ getToken() สำหรับ Android) จากนั้นส่งโทเค็นปัจจุบันไปยังเซิร์ฟเวอร์ของแอปเพื่อจัดเก็บ (พร้อมการประทับเวลา) ซึ่งอาจเป็นงานรายเดือนที่กำหนดค่าให้ครอบคลุมไคลเอ็นต์หรือโทเค็นทั้งหมด
  • เพิ่มตรรกะของเซิร์ฟเวอร์เพื่ออัปเดตการประทับเวลาของโทเค็นเป็นช่วงๆ ไม่ว่าโทเค็นจะมีการเปลี่ยนแปลงหรือไม่ก็ตาม

ดูตัวอย่างตรรกะของ Android สำหรับการอัปเดตโทเค็นเดิมโดยใช้ WorkManager, ได้ที่ การจัดการโทเค็น Cloud Messaging ในบล็อก Firebase

ไม่ว่าคุณจะใช้รูปแบบการกำหนดเวลาแบบใดก็ตาม โปรดอัปเดตโทเค็นเป็นระยะๆ ความถี่ในการอัปเดตเดือนละครั้งเป็นความถี่ที่เหมาะสมระหว่างผลกระทบต่อแบตเตอรี่กับการตรวจหาโทเค็นการลงทะเบียนที่ไม่ได้ใช้งาน การรีเฟรชนี้ยังช่วยให้มั่นใจได้ว่าอุปกรณ์ที่ไม่ได้ใช้งานจะรีเฟรชการลงทะเบียนเมื่อกลับมาใช้งานอีกครั้ง การรีเฟรชบ่อยกว่าสัปดาห์ละครั้งไม่มีประโยชน์

นำการลงทะเบียนที่ล้าสมัยออก

ก่อนส่งข้อความไปยังอุปกรณ์ ให้ตรวจสอบว่าการประทับเวลาการลงทะเบียนของอุปกรณ์อยู่ในช่วงระยะเวลาการล้าสมัย ตัวอย่างเช่น คุณสามารถ ใช้ Cloud Functions for Firebase เพื่อเรียกใช้การตรวจสอบรายวันเพื่อให้แน่ใจว่าการ ประทับเวลาอยู่ในช่วงระยะเวลาการล้าสมัยที่กำหนดไว้ เช่น const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; จากนั้นนำการลงทะเบียนที่ ล้าสมัยออก

exports.pruneRegistrations = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
  // Get all documents where the timestamp exceeds is not within the past month
  const staleRegistrationsResult = await admin.firestore().collection('fcmRegistrations')
      .where("timestamp", "<", Date.now() - EXPIRATION_TIME)
      .get();
  // Delete devices with stale registrations
  staleRegistrationsResult.forEach(function(doc) { doc.ref.delete(); });
});
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 Installation ID (FID) เปลี่ยนไป ซึ่งจะทำให้การสมัครใช้บริการปรากฏขึ้นอีกครั้งโดยอัตโนมัติเมื่อแอปกลับมาใช้งาน
  2. หากอินสแตนซ์ของแอปไม่ได้ใช้งานเป็นเวลา 1 เดือน (หรือระยะเวลาการล้าสมัยของคุณเอง) คุณ ควรยกเลิกการสมัครใช้บริการหัวข้อโดยใช้ Firebase Admin SDK เพื่อลบการแมป Firebase Installation ID กับหัวข้อออกจาก FCM แบ็กเอนด์

ข้อดีของ 2 ขั้นตอนนี้คือการกระจายข้อความจะเกิดขึ้นเร็วขึ้นเนื่องจากมีการลงทะเบียนที่ล้าสมัยน้อยลง และอินสแตนซ์ของแอปที่ล้าสมัยจะสมัครใช้บริการอีกครั้งโดยอัตโนมัติเมื่อกลับมาใช้งาน

วัดความสำเร็จในการส่ง

วิธีที่ดีที่สุดในการดูภาพรวมที่แม่นยำที่สุดของการส่งข้อความคือการส่งข้อความไปยังอินสแตนซ์ของแอปที่ใช้งานอยู่เท่านั้น ซึ่งสำคัญอย่างยิ่งหากคุณส่งข้อความไปยังหัวข้อที่มีผู้สมัครใช้บริการจำนวนมากเป็นประจำ หากผู้สมัครใช้บริการบางส่วนไม่ได้ใช้งาน ผลกระทบต่อสถิติการส่งอาจมีนัยสำคัญเมื่อเวลาผ่านไป

ก่อนกำหนดเป้าหมายข้อความไปยังอินสแตนซ์ของแอป ให้พิจารณาสิ่งต่อไปนี้

  • Google Analytics, ข้อมูลที่บันทึกใน BigQuery หรือสัญญาณการติดตามอื่นๆ บ่งบอกว่าการลงทะเบียนใช้งานอยู่หรือไม่
  • การพยายามส่งครั้งก่อนๆ ล้มเหลวอย่างต่อเนื่องในช่วงระยะเวลาหนึ่งหรือไม่
  • มีการอัปเดต Firebase Installation ID ในเซิร์ฟเวอร์ของคุณในช่วงเดือนที่ผ่านมาหรือไม่
  • สำหรับอุปกรณ์ Android, FCM Data API รายงานเปอร์เซ็นต์สูงของการส่งข้อความล้มเหลวเนื่องจาก droppedDeviceInactiveหรือไม่

ดูข้อมูลเพิ่มเติมเกี่ยวกับการส่งได้ที่ทำความเข้าใจการส่ง ข้อความ