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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

مثال: ذخیره کردن شناسه‌های نصب Firebase و مُهرهای زمان در 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» باموفقیت ثبت یا به‌روز شود، 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 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()
            }
        });

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

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

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

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

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

  • مقداردهی اولیه خودکار فعال است: کیت توسعه نرم‌افزار به‌طور خودکار اطمینان حاصل می‌کند که جدیدترین FID در همگام‌سازی‌های معمول درطول راه‌اندازی برنامه به سرور شما ارسال می‌شود.
  • مقداردهی اولیه خودکار غیرفعال است یا پشتیبانی نمی‌شود: register() را در راه‌اندازی برنامه (برای مثال، در Android، در onCreate() فعالیت اصلی) فراخوانی کنید تا توالی ثبت اجباری شود و تحویل 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 گزارش می‌کند؟

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