روال‌های مطلوب برای مدیریت ثبت FCM

اگر از FCM API برای ساختن درخواست‌های ارسال به‌صورت برنامه‌ریزی‌شده استفاده می‌کنید، ممکن است متوجه شوید که با گذشت زمان، با ارسال پیام به دستگاه‌های غیرفعال با ثبت‌های قدیمی، منابع را هدر می‌دهید. این وضعیت می‌تواند بر داده‌های تحویل پیام گزارش‌شده در کنسول Firebase یا داده‌های صادرشده به BigQuery تأثیر بگذارد و به‌صورت کاهش شدید (اما درواقع نامعتبر) در نرخ تحویل نشان داده شود. این راهنما برخی‌از اقداماتی را که می‌توانید برای کمک به اطمینان از هدف‌یابی کارآمد پیام و گزارش‌دهی معتبر ارسال انجام دهید، مورد بحث قرار می‌دهد.

ثبت‌های قدیمی و منقضی‌شده

ثبت‌های قدیمی با دستگاه‌های غیرفعالی که بیش‌از یک ماه به FCM متصل نشده‌اند مرتبط هستند. با گذشت زمان، احتمال اینکه دستگاه دوباره به FCM متصل شود کمتر و کمتر می‌شود. ارسال پیام و توزیع موضوع برای این ثبت‌نام‌های قدیمی احتمالاً هرگز تحویل داده نخواهد شد.

چند دلیل وجود دارد که چرا ثبت‌نام می‌تواند قدیمی شود. برای مثال، ممکن است دستگاهی که ثبت با آن مرتبط است گم یا خراب شده باشد، یا در انبار گذاشته شده و فراموش شده باشد.

برای Android، وقتی ثبت‌نامی به‌مدت ۲۷۰ روز غیرفعال باشد، FCM آن را منقضی‌شده درنظر می‌گیرد و آن را جمع‌آوری می‌کند. وقتی ثبت‌نامی منقضی می‌شود، FCM آن را به‌عنوان نامعتبر علامت‌گذاری می‌کند و ارسال به آن را رد می‌کند. توجه داشته باشید که «شناسه‌های نصب Firebase» (FIDs) توسط سرویس نصب Firebase (FIS) مدیریت می‌شوند، نه توسط FCM. در موارد نادری که دستگاه دوباره متصل می‌شود و برنامه پس‌از جمع‌آوری زباله ثبت‌نام آن باز می‌شود، برنامه کارخواه دوباره بااستفاده از شناسه نصب Firebase بازیابی‌شده از سرویس‌های نصب Firebase در FCM ثبت‌نام می‌کند. توجه داشته باشید که FID ممکن است تغییر کند؛ برای جزئیات مربوط به زمان صدور مجدد FID، به مدیریت نصب‌های Firebase مراجعه کنید.

برای پلاتفرم‌های دیگر مثل iOS،‏ FCM به سرویس پوش زیربنایی (برای نمونه، APNs) متکی است که انقضای مبتنی بر عدم فعالیت ۲۷۰ روزه یکسان را ندارد. توصیه می‌کنیم که به‌صورت پیش‌دستانه ثبت‌های خود را به‌روز نگه دارید و ثبت‌های قدیمی را حذف کنید.

روال‌های مطلوب پایه

برخی‌از روش‌های اساسی وجود دارد که باید در هر برنامه‌ای که از FCM میاناهای برنامه‌سازی کاربردی برای ساختن درخواست‌های ارسال به‌صورت برنامه‌نویسی‌شده استفاده می‌کند دنبال کنید. روال‌های مطلوب اصلی عبارت‌اند از:

  • «شناسه‌های نصب Firebase»‏ (FID) را از FCM بازیابی کنیدو آن‌ها را در سرور برنامه‌تان ذخیره کنید. نقش مهمی برای سرور این است که FID ثبت‌شده هر مشتری را پیگیری کند و فهرست به‌روزشده‌ای از FIDهای فعال را نگه دارد. اکیداً توصیه می‌کنیم مُهر زمان ثبت را در پایگاه داده‌تان پیاده‌سازی کنید و هر زمان که ثبت بارگذاری شد آن را به‌روز کنید.
  • ثبت‌نام‌های قدیمی را حذف کنید و ثبت‌نام‌های جدید را حفظ کنید. علاوه‌بر برداشتن ثبت‌هایی که FCM دیگر آن‌ها را معتبر نمی‌داند، ممکن است بخواهید نشانه‌های دیگری را که نشان می‌دهد ثبت‌ها قدیمی شده‌اند پایش کنید و آن‌ها را به‌صورت پیش‌دستانه بردارید. این راهنما برخی‌از گزینه‌های شما را برای دستیابی به این هدف مورد بحث قرار می‌دهد.

بازیابی و ذخیره کردن «شناسه‌های نصب Firebase»

در راه‌اندازی اولیه برنامه، کیت توسعه نرم‌افزار FCM نمونه برنامه را در FCM ثبت می‌کند و «شناسه نصب Firebase» (FID) را برمی‌گرداند. این شناسه را باید در درخواست‌های ارسال هدف‌دار از API بگنجانید یا از آن برای اشتراک‌های موضوعی استفاده کنید.

اکیداً توصیه می‌کنیم که FID را همراه با مُهر زمان در سرور برنامه‌تان ذخیره کنید هرگاه بارگذاری می‌شود. با به‌روزرسانی مُهر زمان در هر درخواست بارگذاری، سرور شما می‌داند که نمونه برنامه آخرین‌بار چه زمانی باز شده و با موفقیت با بخش پشتی FCM همگام‌سازی شده است.

بسته به اینکه مقداردهی اولیه خودکار فعال یا غیرفعال باشد (ازجمله پشتیبانی نشود)، باید ثبت‌نام و به‌روزرسانی‌ها را به‌صورت زیر مدیریت کنید:

  • (توصیه‌شده) وقتی مقداردهی اولیه خودکار فعال است: کیت توسعه نرم‌افزار به‌طور خودکار ثبت را به‌روز نگه می‌دارد و تغییرات را پایش می‌کند. فراخوانی برگشتی onRegistered() به‌طور منظم در همگام‌سازی‌های معمول درطول راه‌اندازی برنامه و همچنین هنگام وقوع تغییرات FID فراخوانی می‌شود. کافی است این فراخوانی برگشتی را برای بارگذاری FID در سرورتان پیاده‌سازی کنید و مُهر زمان فعلی را ذخیره کنید.
  • وقتی مقداردهی اولیه خودکار غیرفعال است: onRegistered() فراخوانی برگشتی به‌طور خودکار در شروع فراخوانی نمی‌شود. برای ردیابی ثبت‌نام‌ها و به‌روز نگه داشتن آن‌ها، register() را در راه‌اندازی برنامه فراخوانی کنید؛ برای مثال، در Android، در onCreate() فعالیت اصلی. تماس موفقیت‌آمیز فرایند ثبت FCM را بااستفاده از FID راه‌اندازی می‌کند و آن را به فراخوان onRegistered() شما تحویل می‌دهد، که به برنامه شما اجازه می‌دهد FID را بارگذاری کند و مُهر زمان را در سرور شما به‌روز کند.

مثال: ذخیره کردن شناسه فایل و مُهر زمان در Cloud Firestore

برای مثال، می‌توانید از Cloud Firestore برای ذخیره کردن شناسه‌های نصب Firebase در مجموعه‌ای به‌نام 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» باموفقیت ثبت یا به‌روز شود، 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 ثبت را درصورتی‌که نمونه برنامه آن به‌مدت یک ماه متصل نشده باشد، کهنه درنظر می‌گیرد. هر ثبت‌نامی که قدیمی‌تر از یک ماه باشد احتمالاً دستگاه غیرفعال است؛ دستگاه فعال ثبت‌نام خود را به‌روزرسانی می‌کند.

بسته به مورد استفاده شما، یک ماه ممکن است خیلی کوتاه یا خیلی طولانی باشد، بنابراین تعیین معیارهایی که برای شما مناسب است به عهده شما است.

پاسخ‌های نامعتبر را از زیرینه FCM شناسایی کنید

حتماً پاسخ‌های نامعتبر را از FCM شناسایی کنید و با حذف کردن هرگونه ثبت‌نامی که نامعتبر یا منقضی‌شده شناخته می‌شود از سیستمتان، پاسخ دهید. با «میانای برنامه‌سازی کاربردی HTTP نسخه ۱»، این پیام‌های خطا ممکن است نشان دهد که درخواست ارسال شما ثبت‌های نامعتبر یا منقضی‌شده را هدف‌یابی کرده است:

  • 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()
            }
        });

اگر ثبت دستگاه Android پس‌از ۲۷۰ روز غیرفعال بودن منقضی شود، یا اگر کارخواه به‌طور صریح ثبت را لغو کند، FCM پاسخ نامعتبری برمی‌گرداند. اگر نیاز دارید که براساس تعاریف خودتان، کهنگی را دقیق‌تر پیگیری کنید، می‌توانید به‌صورت پیش‌دستانه ثبت‌های کهنه را بردارید.

ثبت‌نام‌ها را به‌طور منظم به‌روزرسانی کنید

صرف‌نظر از اینکه ثبت‌های شما براساس FIDs یا نشانه‌های ثبت قدیمی باشد، سرورتان باید همیشه مُهر زمان ثبت را در پایگاه داده‌تان در هر درخواست بارگذاری به‌روز کند. این مُهر زمان به‌عنوان سیگنالی برای نصب برنامه عمل می‌کند و به مشتری اطلاع می‌دهد که برنامه باموفقیت باز شده است و با زیرینه FCM همگام‌سازی شده است. بسته به میاناهای برنامه‌سازی کاربردی که استفاده می‌کنید، استراتژی مناسب را پیاده‌سازی کنید:

برای برنامه‌های کارخواه که از FID API استفاده می‌کنند، نیازی نیست کارهای پس‌زمینه دوره‌ای را در برنامه کارخواه خود زمان‌بندی کنید تا ثبت‌نام‌ها را بازیابی یا بازآوری کنید. کیت توسعه نرم‌افزار به‌طور خودکار از بازآوری‌ها تحت مقداردهی اولیه خودکار مراقبت می‌کند، به‌طور منظم FID فعلی صحیح را به onRegistered() فراخوانی برگشتی شما در همگام‌سازی‌های روتین درطول راه‌اندازی برنامه ارائه می‌دهد.

برای به‌روز نگه داشتن سرورتان، استراتژی‌های بارگذاری راه‌اندازی را که در بازیابی و ذخیره کردن شناسه‌های نصب Firebase توضیح داده شده است پیاده‌سازی کنید:

  • مقداردهی اولیه خودکار فعال است: کیت توسعه نرم‌افزار به‌طور خودکار اطمینان حاصل می‌کند که جدیدترین FID درطول همگام‌سازی‌های معمول هنگام راه‌اندازی برنامه به سرور شما ارسال می‌شود.
  • راه‌اندازی خودکار غیرفعال یا پشتیبانی‌نشده: در زمان راه‌اندازی برنامه (برای مثال، در Android، در فعالیت اصلی onCreate()) با فراخوانی register() ثبت توالی را اجباری کنید و ارسال FID را به بازخوان onRegistered() راه‌اندازی کنید.

این استراتژی‌ها تضمین می‌کنند که سرور شما همیشه جدیدترین FID فعال را داشته باشد و می‌تواند به‌طور خودکار از بارگذاری‌های ناموفق بازیابی کند، که باعث می‌شود برنامه بسیار انعطاف‌پذیر باشد.

میاناهای برنامه‌سازی کاربردی منسوخ‌شده ثبت کد

اگر از نشان‌های ثبت قدیمی استفاده می‌کنید، کیت توسعه نرم‌افزار کارخواه به‌طور خودکار مدیریت بازآوری‌ها را در همگام‌سازی‌های معمول انجام نمی‌دهد. بنابراین، توصیه می‌کنیم به‌طور دوره‌ای همه کدهای ثبت را در سرورتان بازیابی و به‌روز کنید. برای این کار باید:

  • منطق برنامه را در برنامه مشتری‌تان اضافه کنید تا بااستفاده از فراخوانی API مناسب (مثل token(completion): برای پلاتفرم‌های Apple یا getToken() برای Android) کد فعلی را بازیابی کنید و سپس کد فعلی را برای ذخیره‌سازی به سرور برنامه‌تان ارسال کنید (با مُهر زمان). این می‌تواند یک کار ماهانه باشد که برای پوشش دادن همه مشتریان یا توکن‌ها پیکربندی شده است.
  • منطق سرور را اضافه کنید تا مُهر زمان رمز را در فواصل زمانی منظم به‌روز کند، صرف‌نظر از اینکه رمز تغییر کرده است یا نه.

برای نمونه‌ای از منطق Android برای به‌روزرسانی نشانه‌های قدیمی بااستفاده از WorkManager، به مدیریت نشانه‌های پیام‌رسانی ابری در وبلاگ 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(); }); });

لغو اشتراک ثبت‌های قدیمی از موضوعات

اگر از موضوعات استفاده می‌کنید، ممکن است بخواهید ثبت‌های قدیمی را از موضوعاتی که در آن‌ها مشترک هستند لغو اشتراک کنید. این کار شامل دو مرحله است:

  1. هرگاه «شناسه نصب Firebase» (FID) تغییر کرد، برنامه‌تان باید دوباره در موضوعات مشترک شود. این کار باعث می‌شود وقتی برنامه‌ای دوباره فعال می‌شود، اشتراک‌ها به‌طور خودکار دوباره ظاهر شوند.
  2. اگر نمونه برنامه به‌مدت یک ماه (یا پنجره کهنگی خودتان) غیرفعال باشد، باید بااستفاده از Firebase Admin SDK اشتراک آن را از موضوعات لغو کنید تا نگاشت «شناسه نصب Firebase» به موضوع از پس‌بک FCM حذف شود.

مزیت این دو مرحله این است که توزیع‌های شما سریع‌تر انجام می‌شود زیرا ثبت‌های قدیمی کمتری برای توزیع وجود دارد و نمونه‌های برنامه قدیمی شما پس‌از فعال شدن مجدد، به‌طور خودکار دوباره مشترک می‌شوند.

سنجش موفقیت در تحویل

برای دریافت دقیق‌ترین تصویر از ارسال پیام، بهتر است فقط به نمونه‌های برنامه که به‌طور فعال استفاده می‌شوند پیام ارسال کنید. این امر به‌ویژه زمانی مهم است که به‌طور منظم به موضوعاتی با تعداد زیادی مشترک پیام ارسال می‌کنید؛ اگر بخشی از آن مشترکان درواقع غیرفعال باشند، تأثیر آن بر آمار تحویل شما می‌تواند درطول زمان قابل‌توجه باشد.

قبل‌از هدف‌یابی پیام‌ها به نمونه برنامه، به موارد زیر توجه کنید:

  • آیا Google Analytics، داده‌های ضبط‌شده در BigQuery، یا دیگر نشان‌های ردیابی نشان می‌دهند که ثبت فعال است؟
  • آیا تلاش‌های قبلی برای تحویل به‌طور مداوم در یک دوره زمانی ناموفق بوده است؟
  • آیا «شناسه نصب Firebase» در ماه گذشته در سرورهایتان به‌روز شده است؟
  • برای دستگاه‌های Android، آیا FCM Data API درصد بالایی از عدم موفقیت در ارسال پیام را به‌دلیل droppedDeviceInactive گزارش می‌کند؟

برای اطلاعات بیشتر درباره تحویل، آشنایی با تحویل پیام را ببینید.