إذا كنت تستخدم واجهات برمجة التطبيقات FCM لإنشاء طلبات الإرسال آليًا، قد تلاحظ بمرور الوقت أنّك تهدر الموارد من خلال إرسال الرسائل إلى الأجهزة غير النشطة التي تحتوي على رموز تسجيل قديمة. يمكن أن يؤثّر هذا الوضع في بيانات تسليم الرسائل التي يتم الإبلاغ عنها في وحدة تحكّم Firebase أو البيانات التي يتم تصديرها إلى BigQuery، ما يؤدي إلى انخفاض كبير (ولكن غير صالح فعليًا) في معدّلات التسليم. يناقش هذا الدليل بعض الإجراءات التي يمكنك اتّخاذها للمساعدة في ضمان استهداف الرسائل بكفاءة وإعداد تقارير تسليم صالحة.
رموز التسجيل القديمة والمنتهية الصلاحية
رموز التسجيل القديمة هي الرموز المرتبطة بالأجهزة غير النشطة التي لم تتصل بـ FCM لأكثر من شهر. بمرور الوقت، يصبح من غير المرجّح على الإطلاق أن يتصل الجهاز بخدمة FCM مرة أخرى. من غير المرجّح على الإطلاق أن يتم تسليم الرسائل المرسَلة والرسائل الموزَّعة على المواضيع لهذه الرموز القديمة.
هناك عدة أسباب تجعل الرمز قديمًا. على سبيل المثال، قد يتم فقدان الجهاز المرتبط بالرمز أو تدميره أو تخزينه ونسيانه.
بالنسبة إلى أجهزة Android، عندما تصل الرموز القديمة إلى 270 يومًا من عدم النشاط، FCM تعتبرها منتهية الصلاحية. بعد انتهاء صلاحية الرمز، FCM تضع عليه علامة غير صالح وترفض عمليات الإرسال إليه. ومع ذلك، FCM تصدر رمزًا جديدًا لمثيل التطبيق في الحالة النادرة التي يتصل فيها الجهاز مرة أخرى ويتم فتح التطبيق.
بالنسبة إلى المنصات الأخرى، مثل iOS، تعتمد خدمة "مراسلة Firebase السحابية" على خدمة الإشعارات الفورية الأساسية (مثل APNs)، التي لا تتضمّن انتهاء صلاحية الرمز المميّز المستند إلى عدم النشاط لمدة 270 يومًا. لذلك، ننصحك بالحفاظ على رموز التسجيل محدّثة وإزالة رموز التسجيل القديمة بشكل استباقي.
أفضل الممارسات الأساسية
هناك بعض الممارسات الأساسية التي يجب اتّباعها في أي تطبيق يستخدم FCM واجهات برمجة التطبيقات لإنشاء طلبات الإرسال آليًا. في ما يلي أفضل الممارسات الرئيسية:
- استرداد رموز التسجيل من FCM وتخزينها على الخادم. يتمثّل دور مهم للخادم في تتبُّع رمز كل عميل والاحتفاظ بقائمة محدّثة بالرموز النشطة. ننصحك بشدة بتنفيذ طابع زمني للرمز في الرمز البرمجي والخوادم، وتعديل هذا الطابع الزمني على فترات منتظمة.
- الحفاظ على رموز التسجيل محدّثة وإزالة الرموز القديمة: بالإضافة إلى إزالة الرموز التي لم تعد FCM تعتبرها صالحة، قد تحتاج إلى مراقبة العلامات الأخرى التي تشير إلى أنّ الرموز أصبحت قديمة وإزالتها بشكل استباقي. يناقش هذا الدليل بعض الخيارات المتاحة لك لتحقيق ذلك.
استرداد رموز التسجيل وتخزينها
عند بدء تشغيل تطبيقك لأول مرة، تنشئ حزمة تطوير البرامج (SDK) في FCM رمز تسجيل لمثيل تطبيق العميل. هذا هو الرمز الذي يجب تضمينه في طلبات الإرسال المستهدَفة من واجهة برمجة التطبيقات، أو إضافته إلى الاشتراكات في المواضيع لاستهداف المواضيع.
ننصحك بشدة بأن يسترد تطبيقك هذا الرمز عند بدء التشغيل الأولي وأن يحفظه على خادم تطبيقك إلى جانب طابع زمني. يجب تنفيذ هذا الطابع الزمني من خلال الرمز البرمجي والخوادم، لأنّ حزم تطوير البرامج (SDK) لا توفّره لك.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 الرمز قديمًا إذا لم يتصل مثيل التطبيق لمدة شهر. من المرجّح أن يكون أي رمز مضى عليه أكثر من شهر جهازًا غير نشط، وإلا كان الجهاز النشط قد جدّد الرمز.
اعتمادًا على حالة الاستخدام، قد يكون شهر واحد قصيرًا جدًا أو طويلاً جدًا، لذا عليك تحديد المعايير المناسبة لك.
رصد استجابات الرموز غير الصالحة من الخادم الخلفي 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 يومًا من عدم النشاط، أو إذا ألغى العميل تسجيله بشكل صريح. إذا كنت بحاجة إلى تتبُّع حالة الرمز القديم بدقة أكبر وفقًا لتعريفاتك الخاصة، يمكنك إزالة رموز التسجيل القديمة بشكل استباقي.
تعديل الرموز بانتظام
ننصحك باسترداد جميع رموز التسجيل وتعديلها بشكل دوري على الخادم. يتطلّب ذلك ما يلي:
- أضف منطق التطبيق في تطبيق العميل لاسترداد الرمز المميز الحالي باستخدام طلب بيانات من واجهة برمجة التطبيقات المناسب (مثل
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.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(); });
});
إلغاء اشتراك الرموز القديمة من المواضيع
إذا كنت تستخدم المواضيع، قد تحتاج أيضًا إلى إلغاء تسجيل الرموز القديمة من المواضيع التي تم الاشتراك فيها. يتضمّن ذلك خطوتَين:
- يجب أن يعيد تطبيقك الاشتراك في المواضيع مرة واحدة في الشهر وكلما تغيّر رمز التسجيل. يشكّل ذلك حلاً ذاتي الإصلاح، حيث تظهر الاشتراكات تلقائيًا مرة أخرى عندما يصبح التطبيق نشطًا مرة أخرى.
- إذا كان مثيل التطبيق غير نشط لمدة شهر واحد (أو فترة انتهاء الصلاحية الخاصة بك)، عليك إلغاء اشتراكه من المواضيع باستخدام Firebase Admin SDK لحذف ربط الرمز المميز بالموضوع من الخادم الخلفي FCM.
تكمن فائدة هاتَين الخطوتَين في أنّ عمليات التوزيع ستحدث بشكل أسرع لأنّ هناك عددًا أقل من الرموز القديمة التي سيتم توزيعها، وسيُعيد مثيل التطبيق القديم الاشتراك تلقائيًا عندما يصبح نشطًا مرة أخرى.
قياس نجاح التسليم
للحصول على صورة أكثر دقة لتسليم الرسائل، من الأفضل إرسال الرسائل إلى أمثلة التطبيقات التي يتم استخدامها بنشاط فقط. يكون ذلك مهمًا بشكل خاص إذا كنت ترسل بانتظام رسائل إلى مواضيع تضم أعدادًا كبيرة من المشتركين، فإذا كان جزء من هؤلاء المشتركين غير نشطين فعليًا، يمكن أن يكون التأثير في إحصاءات التسليم كبيرًا بمرور الوقت.
قبل استهداف الرسائل برمز، يجب مراعاة ما يلي:
- هل تشير "إحصاءات Google" أو البيانات التي تم جمعها في BigQuery أو إشارات التتبُّع الأخرى إلى أنّ الرمز نشط؟
- هل فشلت محاولات التسليم السابقة باستمرار على مدار فترة زمنية؟
- هل تم تعديل رمز التسجيل على الخوادم خلال الشهر الماضي؟
- بالنسبة إلى أجهزة Android، هل تشير واجهة برمجة التطبيقات FCM Data API
إلى نسبة عالية من حالات فشل تسليم الرسائل بسبب
droppedDeviceInactive؟
لمزيد من المعلومات عن التسليم، اطّلِع على مقالة فهم تسليم الرسائل.