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

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

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

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

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

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

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

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

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

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

ดึงข้อมูลและจัดเก็บรหัสการติดตั้ง Firebase

เมื่อเริ่มต้นแอปเป็นครั้งแรก FCM SDK จะลงทะเบียนอินสแตนซ์ของแอป กับ FCM และแสดงรหัสการติดตั้ง Firebase (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)
}

ระบบจะเรียกใช้การเรียกกลับ onRegistered() ทุกครั้งที่ลงทะเบียนหรืออัปเดตรหัสการติดตั้ง Firebase สำเร็จ คุณควรใช้การเรียกกลับนี้เพื่ออัปโหลด 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 IDs:

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

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

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

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

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

ดูตัวอย่างตรรกะของ Android สำหรับการอัปเดตโทเค็นเดิมโดยใช้ WorkManager, ได้ที่ Managing Cloud Messaging Tokens ในบล็อก 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 (FID) เปลี่ยนไป ซึ่งจะทำให้การสมัครใช้บริการปรากฏขึ้นอีกครั้งโดยอัตโนมัติเมื่อแอปกลับมาใช้งาน
  2. หากอินสแตนซ์ของแอปไม่มีการใช้งานเป็นเวลา 1 เดือน (หรือช่วงระยะเวลาที่ถือว่าล้าสมัยของคุณเอง) คุณควรยกเลิกการสมัครใช้บริการหัวข้อโดยใช้ Firebase Admin SDK เพื่อลบการแมปรหัสการติดตั้ง Firebase กับหัวข้อออกจาก FCM แบ็กเอนด์

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

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

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

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

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

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