APNs مقابل FCM لإشعارات الدفع على iOS و Android
مقارنة APNs وFCM لإشعارات iOS وAndroid: دورة حياة الرموز، حدود الحمولة، توقعات التسليم، وقائمة فحص عملية لإصلاح الاشعارات المفقودة.

ما الذي تقارنه (ولماذا يهم)\n\nخدمات APNs (Apple Push Notification service) وFCM (Firebase Cloud Messaging) هي أنابيب التوصيل التي تنقل الرسالة من خادمك إلى الهاتف. هي لا تقرر ماذا يفعل تطبيقك بالرسالة، لكنها تؤثر بشدة على ما إذا كانت الرسالة تصل، مدى سرعة وصولها، وما الشكل الذي يجب أن تكون عليه.\n\nعندما يقول الناس أن إشعار الدفع "يعمل على Android لكن ليس على iOS" (أو العكس)، نادرًا ما يكون السبب خطأ واحدًا فقط. تتعامل iOS وAndroid بشكل مختلف مع الأعمال في الخلفية، حفظ الطاقة، الأذونات، وأولوية الرسائل. قد تتأخر نفس الرسالة، تُستبدل بأحدث منها، تُعرض بدون صوت، أو لا تُعرض أبدًا إذا لم يستطع التطبيق الاستيقاظ لمعالجتها.\n\nيركز هذا المقارنة على الأجزاء التي تسبب المفاجآت في العالم الحقيقي: كيف تتغير رموز الأجهزة بمرور الوقت، ما حجم الحمولة الذي يمكنك إرساله وكيف يجب أن تُبنى، ما مستوى التسليم الذي يمكنك توقعه عمليًا، والأسباب الشائعة لظهور الإشعارات مفقودة.\n\nهذا لا يغطي اختيار واجهة مزود الإشعارات، استراتيجيات التسويق، أو بناء خط أنابيب تحليلات كامل. الهدف هنا هو الموثوقية وتسريع عملية تصحيح الأخطاء.\n\nبعض المصطلحات المستخدمة طوال المقال:\n\n- الرمز (Token): عنوان خاص بالجهاز تصدره APNs أو FCM لإرسال الرسائل إليه.\n- الموضوع (Topic): عنوان جماعي (غالبًا مستخدم مع FCM) يشترك فيه العديد من الأجهزة.\n- القناة (Channel): فئة إشعارات في Android تتحكم في الصوت والأهمية والسلوك.\n- مفتاح التجميع (Collapse key): طريقة لاستبدال الرسائل المعلقة الأقدم بأخرى أحدث.\n- TTL (time to live): المدة التي يمكن أن تنتظر فيها الرسالة للتسليم قبل أن تنتهي صلاحيتها.\n\nإعداد هذه الأساسيات بشكل صحيح يوفر ساعات من التخمين عندما يتصرف "الإشعار البسيط" بشكل مختلف عبر iOS وAndroid.\n\n## كيف تعمل APNs وFCM على مستوى عالٍ\n\nAPNs وFCM كلاهما وسيط بين خادمك وهاتف المستخدم. لا يمكن لتطبيقك توصيل إشعار دفع إلى الجهاز مباشرة عبر الإنترنت بشكل موثوق، لذا يسلم هذه المهمة إلى Apple (APNs) أو Google (FCM)، اللتين تحافظان بالفعل على اتصالات موثوقة مع أجهزتهما.\n\nالتدفق العام متشابه: يحصل تطبيقك على رمز، يرسل الخادم رسالة إلى خدمة الإشعارات باستخدام ذلك الرمز، وتقوم خدمة الإشعارات بتوجيهها إلى الجهاز.\n\n### APNs بلغة بسيطة\n\nعلى iOS، يسجل التطبيق للحصول على إشعارات بعيدة ويطلب عادة إذن المستخدم. بعد ذلك تزود Apple رمز الجهاز. يرسل الخادم (المزود) طلب دفع إلى APNs يتضمن ذلك الرمز والحمولة. يقرر APNs ما إذا كان يمكنه التسليم ثم يوجه الإشعار إلى الجهاز.\n\nيتم توثيق الخادم إلى APNs عادةً باستخدام مصادقة قائمة على الرمز (مفتاح توقيع). الإعدادات القديمة تستخدم شهادات.\n\n### FCM بلغة بسيطة\n\nعلى Android، يسجل مثيل التطبيق لدى FCM ويتلقى رمز تسجيل. يرسل الخادم رسالة إلى FCM، وتقوم FCM بتوجيهها إلى الجهاز الصحيح. اعتمادًا على حالة التطبيق ونوع الرسالة، قد تعرض FCM إشعارًا تلقائيًا أو تسلم البيانات للتطبيق لمعالجتها.\n\nيتوثق الخادم إلى FCM باستخدام بيانات اعتماد الخادم (مفتاح API أو حساب خدمة).\n\nما تتحكم به: كود التطبيق، متى تطلب الإذن، تخزين الرموز، منطق الخادم، والحمولة التي ترسلها. ما تتحكم به Apple وGoogle: شبكة التوصيل، إمكانية الوصول، قواعد التقييد، والعديد من شروط الميل الأخير مثل حفظ الطاقة وسياسات النظام.\n\n## دورة حياة الرمز: كيف تُصدر الرموز، تُجدد وتُلغى\n\nأكبر فرق يومي بين APNs وFCM هو أن الرموز ليست "مضبوطة مرة واحدة للأبد". عاملها كعناوين يمكن أن تتغير دون سابق إنذار.\n\nعلى iOS، يرتبط رمز جهاز APNs بالجهاز وتطبيقك وإعداد المطور الخاص بك لدى Apple. قد يتغير بعد إعادة تثبيت التطبيق، استعادة الجهاز، بعض تحديثات النظام، أو عند التبديل بين بيئات الإشعارات (sandbox vs production) أثناء التطوير.\n\nعلى Android، قد يتجدد رمز تسجيل FCM عند استعادة التطبيق على جهاز جديد، عند مسح بيانات التطبيق، عندما تدور Google الرمز، أو عند إعادة تثبيت التطبيق. يجب على تطبيقك توقع أحداث التجديد وإرسال الرمز الجديد إلى خادمك بسرعة.\n\nقاعدة بسيطة: دائمًا قم بعمل upsert للرموز، لا تُدرجها وتنسى. عند تخزين الرموز، احتفظ بسياق كافٍ لتجنب التكرار والأهداف الخاطئة:\n\n- معرف المستخدم أو الحساب (إن وُجد)\n- حزمة التطبيق/البيئة\n- المنصة (iOS/Android)\n- قيمة الرمز والطابع الزمني لـ"آخر ظهور"\n- حالة الاشتراك (الإذن ممنوح/مرفوض)\n\nحذف الرموز مهم أيضًا. عادةً ما تعرف أن رمزًا بات ميتًا من أخطاء التسليم، وليس من إشارة "إلغاء التثبيت" نظيفة. إذا أعاد APNs خطأ مثل Unregistered (غالبًا مع حالة 410)، أو قال FCM NotRegistered/Unregistered، احذف ذلك الرمز فورًا حتى تتوقف عن المحاولة إلى الأبد.\n\nطريقة سهلة لتسريب تحديثات خاصة: يقوم عميل بتسجيل الخروج ويقوم آخر بتسجيل الدخول على نفس الهاتف. إذا لم تمسح أو تعيد ربط الرمز عند تسجيل الخروج، فقد ترسل إشعارات إلى الشخص الخطأ رغم أن التسليم "يعمل".\n\n## قيود الحمولة وبُنى الرسائل المختلفة\n\nأكبر فرق عملي بين APNs وFCM هو ما يمكنك وضعه في رسالة وكيف يتعامل الهاتف معها عند وصولها.\n\nتعتمد معظم الفرق على مجموعة صغيرة من الحقول:\n\n- عنوان ونص الرسالة\n- عداد الشارات (Badge) على iOS\n- الصوت (افتراضي أو مخصص)\n- بيانات مخصصة على شكل أزواج مفتاح/قيمة (مثل order_id, status)\n\n### حدود الحجم: اجعل الإشعار صغيرًا\n\nكلا الخدمتين لهما حدود حجم للحمولة، والحد يشمل بياناتك المخصصة. عند الوصول إلى الحد، قد يفشل التسليم أو لا يتصرف الإشعار كما تتوقع.\n\nنمط موثوق هو إرسال إشعار قصير مع معرف، ثم جلب التفاصيل من الخادم:\n\nمثال: بدلًا من إرسال ملخص كامل للطلب، أرسل { "type": "order_update", "order_id": "123" } ودع التطبيق يستدعي الـ API الخاص بك لتحميل الحالة الأحدث.\n\n### السلوك: بيانات فقط مقابل الإشعار المرئي\n\nعلى Android، رسالة FCM التي تحتوي على حمولة "notification" تُعرض عادةً بواسطة النظام عندما يكون التطبيق في الخلفية. الرسالة التي تحتوي على بيانات فقط تُسلم إلى شفرة التطبيق، لكنها قد تتأخر أو تُمنع بواسطة قيود الخلفية وإعدادات البطارية.\n\nعلى iOS، التنبيهات (العنوان/النص) واضحة، لكن التحديثات الخلفية أكثر صرامة. الدفع الخلفي لا يضمن تشغيل كودك فورًا. اعتبره تلميحًا للتحديث وليس محفزًا فوريًا.\n\nإذا كنت بحاجة إلى موثوقية، اجعل الحمولة قليلة، أدرج معرفًا ثابتًا، وصمم التطبيق للمصالحة عند الفتح أو الاستئناف.\n\n## توقعات التسليم وما الذي يمكن أن يوقف الإشعار\n\nمع كل من APNs وFCM، التسليم يكون بأفضل محاولة. سيحاول الموفر توصيل رسالتك، لكنه لا يضمن أن الجهاز سيعرضها.\n\nقابلية الوصول أول محدد. ترسل إشعارًا مع TTL أو تاريخ انتهاء. إذا عاد الجهاز للاتصال بعد نافذة الصلاحية، تُرمى الرسالة. إذا كانت TTL طويلة جدًا، قد يرى المستخدم تنبيهًا قديمًا لاحقًا، ويبدو ذلك كخلل.\n\nالأولوية تؤثر على التوقيت، لكنها ليست ترقية مجانية. يمكن أن تساعد الأولوية العالية على وصول الرسائل الحساسة زمنياً أسرع، خاصة عندما يكون الجهاز نائمًا. الإفراط في استخدامها قد يؤدي إلى تقييدك، استهلاك بطارية أعلى، أو تصنيف النظام لتطبيقك كمصدر إزعاج.\n\nيدعم كلا النظامين التجميع بحيث تستبدل رسالة أحدث رسالة أقدم بدلًا من التكديس. يستخدم APNs معرف التجميع، ويستخدم FCM مفتاح التجميع. إذا جمعت على شيء مثل order_status، قد يرى المستخدم حالة واحدة فقط هي الأحدث بدلًا من كل خطوة.\n\nحتى لو سلّم الموفر الرسالة بنجاح، قد يمنع الهاتف المستخدم من رؤيتها:\n\n- أوضاع عدم الإزعاج أو Focus التي يمكن أن تكتم أو تخفي التنبيهات\n- إعدادات إشعارات التطبيق التي يمكن تعطيلها أو ضبطها على تسليم هادئ\n- قنوات إشعارات Android التي يمكن إيقافها لفئة معينة\n- قيود الخلفية أو موفّرو حفظ البطارية قد يؤخرون التسليم\n- قد يقمع نظام التشغيل التكرارات إذا نشر تطبيقك تنبيهات متشابهة كثيرة\n\nعامل الإشعارات كوسيلة نقل غير موثوقة: احتفظ بالحالة المهمة في الخادم، واجعل التطبيق يحدث الحالة عند الفتح حتى وإن لم يظهر الإشعار.\n\n## الأذونات وإعدادات الجهاز التي تؤثر على التسليم\n\nالعديد من "مشاكل التسليم" هي في الواقع قضايا أذونات وإعدادات.\n\nعلى iOS، موجه الإذن الأول مهم. إذا نقر المستخدم "عدم السماح"، فلن تظهر الإشعارات حتى يغير ذلك من إعدادات النظام. حتى بعد الموافقة، يمكنهم تعطيل شاشة القفل، مركز الإشعارات، البانرات، الأصوات، أو الشارات. أوضاع Focus وScheduled Summary يمكن أن تخفي أو تؤخر التنبيهات أيضًا.\n\nعلى Android، المتطلبات تعتمد على إصدار النظام. الإصدارات الأحدث تتطلب إذن إشعارات وقت التشغيل، لذا قد يتوقف التطبيق عن عرض الإشعارات بعد تحديث التطبيق حتى يوافق المستخدم مرة أخرى. تعتمد الرؤية أيضًا على قنوات الإشعارات؛ إذا كانت القناة مكتومة أو منخفضة الأهمية، قد تصل الرسائل لكنها لا تقاطع المستخدم.\n\nقيود الخلفية يمكن أن تكسر التوقعات أيضًا. وضع الطاقة المنخفضة على iOS وتحسينات البطارية على Android قد تؤخر الأعمال الخلفية، تمنع البيانات في الخلفية، أو تمنع التطبيق من معالجة رسالة بيانات فقط.\n\nلتأكيد ما يحدث، سجّل ما يراه الجهاز، وليس ما أرسله الخادم فقط:\n\n- سجلات داخل التطبيق: "الإذن ممنوح"، "الرمز مسجل"، "الإشعار تم استلامه"، "الإشعار عُرض"\n- مؤشرات النظام: حالة إعدادات الإشعارات (مُمكَّنة/مكتومة/أهمية القناة) ووضع البطارية\n- ردود دفع: هل استلم تطبيقك الرسالة في الواجهة الأمامية/الخلفية\n\nحتى إذا بُني خادمك بأداة بدون كود، فإن تسجيل العميل هو ما يميز "الرسالة لم تُستلم" عن "تم الاستلام لكن تم قمعها".\n\n## خطوة بخطوة: كيفية استكشاف إشعارات مفقودة\n\nعندما تختفي رسالة دفع، عاملها كسلسلة: الرمز، الموفر، الحمولة، وسلوك التطبيق. الأعراض قد تبدو متماثلة على iOS وAndroid، لذا افحص نفس النقاط بالترتيب.\n\n- تأكد أنك ترسل إلى رمز حديث. قارن الرمز المخزن على الخادم مع الرمز الذي أبلغه التطبيق مؤخرًا. سجّل آخر مرة استلمت فيها كل رمز.\n- تحقق من صحة الحمولة قبل الإرسال. اجعلها تحت حدود المنصة، استخدم الحقول المطلوبة، وتجنب JSON معطوب. إذا أرسلت رسائل بيانات فقط، تأكد أن التطبيق مُعد لمعالجتها.\n- تحقق من بيانات اعتماد الموفر والبيئة. بالنسبة لـ APNs، تحقق من المفتاح/الشهادة، الفريق، معرف الحزمة، وما إذا كنت تستهدف sandbox أم production. بالنسبة لـ FCM، تحقق من بيانات اعتماد المشروع الصحيحة.\n\nثم حدد ما إذا كانت المشكلة في محتوى الرسالة أو سلوك الجهاز/التطبيق:\n\n- أرسل إشعار اختبار بسيط. حمولة عنوان/نص صغيرة تساعد على تأكيد أن النقل يعمل.\n- تحقق من معالجات جانب التطبيق وسلوك الواجهة الأمامية. كثير من الإشعارات "المفقودة" تُستقبل لكن لا تُعرض. بعض التطبيقات تُقمع البانرات في الواجهة الأمامية عن قصد.\n- غيّر متغيرًا واحدًا في كل مرة. جرِّب جهازًا ثانٍ، إصدار نظام تشغيل مختلف، Wi-Fi مقابل خلوي، وحساب مستخدم مختلف. إذا فشل حساب واحد فقط، فغالبًا ما يشير ذلك إلى رموز قديمة أو استهداف خاطئ على الخادم.\n\nنمط عملي: إذا أبلغ مستخدمو iOS عن حالات فقد بينما على Android كل شيء جيد، ابدأ بإرسال تنبيه مرئي بسيط على iOS. إذا نجح، ركز على بنية الحمولة ومعالجة التطبيق. إذا لم ينجح، راجع الرموز وبيانات اعتماد APNs/البيئة.\n\n## أخطاء شائعة تسبب فشلًا صامتًا\n\nمعظم مشاكل الدفع ليست انقطاعات خدمة. هي عدم تطابقات صغيرة بين ما يتوقعه تطبيقك وما تقبله APNs أو FCM، أو ما يسمح به الهاتف.\n\nالأكثر شيوعًا هو الإرسال إلى رمز لم يعد صالحًا. تتغير الرموز بعد إعادة التثبيت، الاستعادة، أو التجديد. إذا استمر خادمك في استخدام القيمة القديمة، تذهب الرسائل إلى العدم.\n\nخطأ آخر هو اعتبار تسليم الإشعار مضمونًا. التسليم بأفضل محاولة يعني أن الرسائل المتأخرة أو المفقودة أمر طبيعي عند وجود أجهزة غير متصلة أو تحت قواعد حفظ الطاقة. للأحداث المهمة (تحديثات الطلب، تنبيهات الأمان)، تحتاج مسارًا احتياطيًا داخل التطبيق مثل جلب الحالة الأحدث عند الفتح.\n\nأسباب شائعة لفقدان الإشعارات:\n\n- رموز iOS أو Android قديمة بعد إعادة التثبيت/التجديد\n- تجاوز حدود حمولة إشعارات الدفع (بيانات مخصصة كبيرة، صور كبيرة، سلاسل طويلة)\n- الاعتماد على التسليم الخلفي لتحديثات صامتة ثم التعرض للتقييد من النظام\n- خلط بيئات iOS (تطوير مقابل إنتاج)، بحيث لا يتطابق الرمز ونقطة نهاية APNs\n- تجاهل اختيار المستخدم، أوضاع Focus/Do Not Disturb، قنوات الإشعارات المعطلة (Android)، أو أذونات التطبيق\n\nمثال: يرسل تطبيق تجزئة إشعار "تم شحن الطلب" مع بلوبر كبير من بيانات التتبع. تبدو نداءات الإرسال صحيحة، لكن الحمولة تُرفض أو تُختصر، فلا يرى المستخدم شيئًا. اجعل الإشعار خفيفًا وضع التفاصيل خلف استدعاء API.\n\n## قائمة تحقق سريعة قبل لوم APNs أو FCM\n\nقبل أن تفترض أن المشكلة من الموفر، قم بفحص سريع للنقاط التالية:\n\n- تأكد أن الرمز صحيح للمستخدم والجهاز. يجب أن يكون موجودًا، محدثًا مؤخرًا، ومرتبطًا بالجلسة الصحيحة.\n- تحقق من أن بيانات اعتماد الموفر صالحة الآن. افحص مفاتيح/شهادات APNs وبيانات اعتماد FCM وتأكد أنها تطابق التطبيق/المشروع الصحيح.\n- تحقق من شكل وحجم الحمولة. ابق تحت الحدود واستخدم الحقول الصحيحة.\n- اضبط TTL، الأولوية، والتجميع عن قصد. TTL القصير قد تنتهي صلاحيته قبل أن يعود الهاتف للاتصال. الأولوية المنخفضة قد تؤخر التسليم. التجميع قد يستبدل الرسائل الأقدم.\n- فصل "الخادم قبل القبول" عن "الجهاز يعرض". قارن سجلات الخادم (الطلب/الاستجابة/معرّف الرسالة) مع سجلات العميل (الرمز المستخدم، المعالج المستدعى).\n\nثم قم بفحص جهاز سريع: الإشعارات مسموح بها للتطبيق، القناة/الفئة صحيحة (قنوات Android غالبًا ما تسبب المشكلة)، أوضاع Focus/Do Not Disturb، وقيود الخلفية.\n\n## مثال: تشخيص إشعار تحديث طلب مفقود\n\nعميل الدعم يضغط "إرسال تحديث الطلب" للطلب #1842. تُظهر سجلات الخادم "تم إرسال الإشعار"، لكن العميل لا يرى شيئًا على iPhone أو هاتف Android.\n\nابدأ من الخادم. معظم الإشعارات "المفقودة" إما لم تُقبل من قبل خدمة الدفع، أو قُبلت ثم حُذفت لاحقًا لأن الجهاز لا يستطيع (أو لا يريد) عرضها.\n\n### فحوصات الخادم أولًا\n\nابحث عن محاولة إرسال واحدة قابلة للتتبع (كل تحديث طلب يجب أن ينتج طلب دفع واحد). ثم تحقق من:\n\n- الرمز المستخدم هو أحدث رمز مخزن لذلك المستخدم والجهاز.\n- استجابة مزود الدفع ناجحة، وحفظت أي رموز خطأ.\n- الحمولة تطابق قواعد المنصة (حدود الحجم، الحقول المطلوبة، JSON صالح).\n- المصادقة صالحة (مفتاح/شهادة APNs ومعرف الفريق/الحزمة، أو بيانات اعتماد FCM).\n- استهدفت البيئة iOS الصحيحة (sandbox مقابل production).\n\nإذا أظهرت سجلاتك رفضًا مثل "unregistered/invalid token"، فهذه مشكلة دورة حياة الرمز. إذا قبل الموفر الرسالة لكن لم يصل شيء، ركز على نوع الحمولة وسلوك نظام التشغيل.\n\n### الفحوصات على الهاتف\n\nتحقق الآن من أن الهاتف مسموح له بعرض التنبيه:\n\n- الإشعارات مفعلة للتطبيق (ومسموح بها لشاشة القفل/البانرات).\n- أوضاع Focus/Do Not Disturb أو ملخصات الإشعارات لا تخفيها.\n- أوضاع حفظ البطارية لا تقيد الأعمال الخلفية (أكثر شيوعًا على Android).\n- حالة التطبيق تطابق نوع الرسالة (الواجهة الأمامية قد تمتص التنبيهات).\n\nنتيجة شائعة: الرمز جيد، لكن الرسالة من نوع بيانات فقط (Android) أو تفتقد الإعدادات الصحيحة على iOS للتعامل في الخلفية، لذلك لا يعرض النظام أي تنبيه. الحل هو إرسال نوع الحمولة الصحيح لما تريده (تنبيه مرئي مقابل تحديث خلفي) والحفاظ على سجلات نظيفة لتحديثات الرموز واستجابات الموفر.\n\n## الخطوات التالية: اجعل الإشعارات أكثر موثوقية في منتجك\n\nتبدو إشعارات الدفع بسيطة حتى تصبح ميزة أساسية. الموثوقية تأتي من القطع التي تتحكم بها: نظافة الرموز، انضباط الحمولة، ومسار احتياطي.\n\nخطط لفقدان بعض الرسائل. الإشعارات جيدة للحظات "انظر الآن"، لكنها لا ينبغي أن تكون الطريق الوحيد للأحداث الحرجة. صندوق داخلي داخل التطبيق يساعد المستخدمين على اللحاق لاحقًا، والبريد الإلكتروني أو SMS يمكن أن يغطي الإجراءات عالية القيمة مثل إعادة تعيين كلمة المرور أو مشكلات الدفع.\n\nاجعل الحمولة خفيفة. اعتبر حمولة الدفع كمحفز، لا كرسالة كاملة. أرسل نوع الحدث ومعرفًا، ثم اجلب التفاصيل من واجهة برمجة التطبيقات عند فتح التطبيق أو عند استلام تحديث خلفي مناسب.\n\nاكتب دفتر إجراءات قصير لفريقك حتى يظل تصحيح الأخطاء متسقًا: حالة الاشتراك، حداثة الرموز، رموز استجابة الموفر، حجم/شكل الحمولة، والبيئة/بيانات الاعتماد.\n\nإذا كنت تبني باستخدام AppMaster (appmaster.io)، فقد يكون من الملائم الاحتفاظ بتخزين الرموز، سجلات التدقيق، ومنطق تشغيل الإرسال في باكند واحد، مع إرسال تطبيقات iOS وAndroid أصلية تتعامل مع APNs وFCM بشكل صحيح.
الأسئلة الشائعة
APNs هي خدمة توصيل إشعارات الدفع من Apple لنظام iOS، وFCM هي خدمة التوصيل من Google لأندرويد (ويمكن أيضًا استهداف iOS عبر APNs). تطبيقك لا يزال يقرر كيف يتعامل مع الرسالة، لكن هذه الخدمات تحدد طريقة المصادقة، شكل الحمولة، وسلوك التسليم المتوقع.
عامل الرموز كعناوين قابلة للتغيير. خزّنها مع تفاصيل المنصة والبيئة، حدّثها كلما أبلغ التطبيق عن قيمة جديدة، واحذفها عندما يخبرك الموفر أنها غير صالحة. القاعدة العملية هي upsert للرموز وحفظ طابع زمني لـ"آخر ظهور" حتى تكتشف السجلات القديمة بسرعة.
على iOS، يتغير الرمز غالبًا بعد إعادة التثبيت، استعادة الجهاز، بعض تحديثات النظام، أو عند التبديل بين بيئات التطوير (sandbox vs production). على Android، قد يتجدد رمز FCM بعد إعادة التثبيت، عند مسح بيانات التطبيق، استعادة الجهاز، أو عندما تدور Google الرموز. يجب على التطبيق الاستماع لأحداث التحديث وإرسال الرمز الجديد فورًا إلى الخادم.
اجعل حمولة الإشعار صغيرة وتعاملها كمحفز. أرسل عنوانًا/نصًا قصيرًا (إذا أردت تنبيهًا مرئيًا) مع معرف ثابت مثل order_id، ودع التطبيق يجلب التفاصيل الكاملة من الـ API. هذا يتجنب حدود الحجم ويجعل السلوك أكثر اتساقًا بين المنصات.
حمولة "الإشعار" مخصصة للعرض للمستخدم، بينما حمولة "البيانات فقط" مخصصة لمعالجة التطبيق. على Android، قد تتأخر رسائل البيانات أو تُمنع بسبب قيود الخلفية وحالة البطارية، لذا فهي ليست طريقة موثوقة لتنفيذ عمل فوري. على iOS، التحديثات الخلفية أيضًا ليست مضمونة لتشغيل الكود فورًا، بل تُعامل كإشارة لتحديث الحالة.
لا، التسليم يكون بأفضل محاولة. حتى لو قبلت APNs أو FCM طلبك، قد يكون الجهاز غير متصل، تنتهي صلاحية الرسالة حسب TTL، قد يقوم النظام بفرض قيود، أو قد تُكتم التنبيهات بواسطة إعدادات المستخدم. صمم تطبيقك بحيث تكون الحالة الحرجة صحيحة عند فتح المستخدم للتطبيق حتى لو لم يظهر الإشعار.
ابدأ بفصل "مرسَل" عن "معروض". تأكد من أن الرمز حديث، أرسل حمولة اختبار قصيرة لعنوان/نص، وتحقق من أنك تستخدم بيانات اعتماد APNs/FCM الصحيحة وبيئة iOS الملائمة. إذا قبل الموفر الرسالة، فافحص إعدادات الهاتف مثل Focus/Do Not Disturb، أذونات التطبيق، وقنوات الإشعارات على Android، لأن الرسالة قد تُستقبل لكن تُكتم.
على iOS، معظم المشاكل تنبع من رفض الأذونات، أو أوضاع Focus، أو استهداف بيئة APNs خاطئة (sandbox vs production). على Android، الحواجز الشائعة هي إذن الإشعارات وقت التشغيل في الإصدارات الأحدث، قنوات إشعارات مكتومة أو منخفضة الأهمية، وتحسينات البطارية التي تؤخر معالجة الخلفية. نفس إرسال الخادم قد يبدو سليمًا بينما يمنع الجهاز المستخدم من رؤية الإشعارات.
TTL يحدد المدة التي ينبغي على الموفر الاحتفاظ فيها بالمحاولة أثناء عدم اتصال الجهاز، وإعدادات التجميع (collapse) تقرر ما إذا كانت الرسائل الأحدث تستبدل القديمة. TTL قصير قد يجعل الإشعارات تختفي إذا كان الهاتف غير متصل لفترة، ومفاتيح التجميع قد تجعل المستخدم يرى التحديث الأحدث فقط بدلاً من كل خطوة.
احتفظ بتخزين الرموز، قواعد الاستهداف، وسجلات الإرسال معًا حتى يمكنك تتبع كل محاولة إرسال نهاية إلى نهاية. AppMaster (appmaster.io) يساعد على مركزية جداول الرموز، سجلات التدقيق، ومنطق تشغيل الإرسال في باكند واحد، بينما تبقى تطبيقات iOS وAndroid الأصلية مسؤولة عن التعامل الصحيح مع APNs وFCM. المفتاح هو تسجيل تحديثات الرموز، استجابات الموفر، واستلام العميل حتى تحدد ما إذا كانت المشكلة من الخادم أو الموفر أو الجهاز.
أكثر الأسباب شيوعًا للفشل الصامت هي إرسال رسالة إلى رمز قديم، تجاوز حدود الحمولة، الاعتماد على التسليم في الخلفية الذي يتعرض لتقييد من النظام، أو مزيج بين بيئات iOS (تطوير مقابل إنتاج). تحقق من صلاحية الرموز، حجم وشكل الحمولة، أذونات المستخدم، وقنوات الإشعارات على Android.


