استلام الرسائل في تطبيق Android

يختلف سلوك إشعارات Firebase بناءً على حالة المقدّمة أو الخلفية للتطبيق المستلِم. إذا أردت أن تتلقّى التطبيقات التي تعمل في المقدّمة رسائل إشعارات أو رسائل بيانات، عليك كتابة رمز برمجي للتعامل مع معاودة الاتصال بـ onMessageReceived. للحصول على توضيح للاختلاف بين رسائل الإشعارات ورسائل البيانات، راجِع أنواع الرسائل.

التعامل مع الرسائل

لتلقّي الرسائل، استخدِم خدمة تمتد إلى FirebaseMessagingService. يجب أن تلغي الخدمة استدعاءَي onMessageReceived وonDeletedMessages.

قد تكون الفترة الزمنية لمعالجة الرسالة أقصر من 20 ثانية بناءً على التأخيرات التي تحدث قبل الاتصال بـ onMessageReceived، بما في ذلك حالات التأخير في نظام التشغيل أو وقت بدء تشغيل التطبيق أو حظر سلسلة التعليمات الرئيسية بسبب عمليات أخرى أو استغراق مكالمات onMessageReceived السابقة وقتًا طويلاً. وبعد انقضاء هذه المدة، قد تتأثّر قدرتك على إنجاز مهامك من خلال السلوكيات المختلفة لنظام التشغيل، مثل إيقاف العمليات في Android أو حدود التنفيذ في الخلفية لنظام التشغيل Android O.

يتوفر onMessageReceived لمعظم أنواع الرسائل، مع الاستثناءات التالية:

  • رسائل الإشعارات التي يتم تسليمها عندما يعمل تطبيقك في الخلفية: في هذه الحالة، يتم إرسال الإشعار إلى لوحة نظام الجهاز. عندما ينقر المستخدم على أحد الإشعارات، يتم فتح مشغّل التطبيقات تلقائيًا.

  • الرسائل التي تحتوي على كل من الإشعارات وحمولة البيانات عند استلامها في الخلفية وفي هذه الحالة، يتم إرسال الإشعار إلى لوحة النظام في الجهاز، ويتم تسليم حمولة البيانات في الخصائص الإضافية لغرض نشاط مشغّل التطبيقات.

وباختصار:

حالة التطبيق الإشعار البيانات كلاهما
لون الواجهة onMessageReceived onMessageReceived onMessageReceived
الخلفية علبة النظام onMessageReceived إشعار: لوحة النظام
البيانات: في التفاصيل الإضافية للغرض
لمزيد من المعلومات عن أنواع الرسائل، يرجى الاطّلاع على الإشعارات ورسائل البيانات.

تعديل بيان التطبيق

لاستخدام FirebaseMessagingService، يجب إضافة ما يلي في بيان التطبيق:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

ننصحك أيضًا بضبط القيم التلقائية لتخصيص مظهر الإشعارات. يمكنك تحديد رمز تلقائي مخصّص ولون تلقائي مخصّص يتم تطبيقه عندما لا يتم ضبط قيم مكافئة في حمولة الإشعارات.

أضِف هذه الخطوط داخل العلامة application لضبط الرمز التلقائي المخصّص واللون المخصّص:

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

يعرض Android الرمز التلقائي المخصّص

  • كل رسائل الإشعارات المُرسَلة من مؤلف الإشعارات
  • أي رسالة إشعار لا يتم فيها ضبط الرمز بشكل صريح في حمولة الإشعارات

يستخدم Android اللون الافتراضي المخصص

  • كل رسائل الإشعارات المُرسَلة من مؤلف الإشعارات
  • تشير هذه السمة إلى أي رسالة إشعار لا يتم فيها ضبط اللون في حمولة الإشعارات بشكل صريح.

إذا لم يتم ضبط رمز تلقائي مخصَّص ولم يتم ضبط رمز في البيانات الأساسية للإشعارات، سيعرض Android رمز التطبيق باللون الأبيض.

إلغاء "onMessageReceived"

من خلال تجاوز الطريقة FirebaseMessagingService.onMessageReceived، يمكنك تنفيذ الإجراءات استنادًا إلى الكائن RemoteMessage الذي تم استلامه والحصول على بيانات الرسالة:

Kotlin+KTX

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: ${remoteMessage.from}")

    // Check if message contains a data payload.
    if (remoteMessage.data.isNotEmpty()) {
        Log.d(TAG, "Message data payload: ${remoteMessage.data}")

        // Check if data needs to be processed by long running job
        if (needsToBeScheduled()) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob()
        } else {
            // Handle message within 10 seconds
            handleNow()
        }
    }

    // Check if message contains a notification payload.
    remoteMessage.notification?.let {
        Log.d(TAG, "Message Notification Body: ${it.body}")
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

Java

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob();
        } else {
            // Handle message within 10 seconds
            handleNow();
        }

    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

إلغاء "onDeletedMessages"

في بعض الحالات، قد لا تعمل ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" على تسليم رسالة. ويحدث ذلك عندما يكون هناك عدد كبير جدًا من الرسائل (أكثر من 100 رسالة) معلّقة لتطبيقك على جهاز معيّن أثناء اتصاله أو إذا كان الجهاز غير متصل بالمراسلة عبر السحابة الإلكترونية من Firebase لأكثر من شهر واحد. في هذه الحالات، قد تتلقّى معاودة الاتصال بالرقم FirebaseMessagingService.onDeletedMessages() عندما يتلقّى مثيل التطبيق هذه الردّ، من المفترض أن يُجري مزامنة كاملة مع خادم تطبيقك. إذا لم ترسل رسالة إلى التطبيق على ذلك الجهاز خلال الأسابيع الأربعة الماضية، لن تتصل ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" برقم onDeletedMessages().

التعامل مع رسائل الإشعارات في تطبيق يعمل في الخلفية

عندما يعمل التطبيق في الخلفية، يوجّه Android رسائل الإشعارات إلى لوحة النظام. عندما ينقر المستخدم على الإشعار، يتم فتح مشغّل التطبيقات تلقائيًا.

ويشمل ذلك الرسائل التي تحتوي على كل من الإشعارات وحمولة البيانات (وجميع الرسائل المرسلة من "وحدة تحكّم الإشعارات"). وفي هذه الحالات، يتم إرسال الإشعار إلى لوحة النظام في الجهاز، ويتم تسليم حمولة البيانات في الإضافات المقصودة من نشاط مشغّل التطبيقات.

للحصول على إحصاءات بشأن تسليم الرسائل إلى تطبيقك، راجِع لوحة بيانات إعداد تقارير خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" التي تسجِّل عدد الرسائل المرسَلة وفتحها على أجهزة Apple وAndroid، بالإضافة إلى بيانات "مرات الظهور" (الإشعارات التي يراها المستخدمون) لتطبيقات Android.

تلقّي رسائل "المراسلة عبر السحابة الإلكترونية من Firebase" في وضع التشغيل المباشر

يمكن للمطوّرين الذين يريدون إرسال رسائل "المراسلة عبر السحابة الإلكترونية من Firebase" إلى التطبيقات حتى قبل فتح قفل الجهاز تفعيل تطبيق Android لتلقّي الرسائل عندما يكون الجهاز في وضع التشغيل المباشر. على سبيل المثال، قد ترغب في أن يتلقى مستخدمو تطبيقك إشعارات التنبيه حتى على جهاز مُقفَل.

عند إنشاء حالة الاستخدام هذه، اتّبِع أفضل الممارسات والقيود العامة لوضع التشغيل المباشر. ويجب مراعاة إمكانية رؤية الرسائل المباشرة التي تم تفعيل ميزة التمهيد (بدء التشغيل)، حيث يمكن لأي مستخدم لديه حق الوصول إلى الجهاز عرض هذه الرسائل بدون إدخال بيانات اعتماد المستخدم.

المتطلّبات الأساسية

  • يجب إعداد الجهاز على وضع التشغيل المباشر.
  • يجب أن يتوفّر على الجهاز إصدار حديث من خدمات Google Play مثبَّت (الإصدار 19.0.54 أو إصدار أحدث).
  • يجب أن يستخدم التطبيق حزمة تطوير البرامج (SDK) لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" (com.google.firebase:firebase-messaging) لتلقّي رسائل المراسلة عبر السحابة الإلكترونية من Firebase.

تفعيل التعامل المباشر مع الرسائل في وضع التشغيل في تطبيقك

  1. في ملف Gradle على مستوى التطبيق، أضِف تبعية إلى مكتبة دعم التشغيل المباشر للمراسلة عبر السحابة الإلكترونية من Firebase:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. يمكنك جعل تمهيد FirebaseMessagingService المباشر للتطبيق على دراية بها من خلال إضافة السمة android:directBootAware="true" في بيان التطبيق:

    <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false"
        android:directBootAware="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    

من المهم التأكّد من إمكانية تشغيل FirebaseMessagingService في وضع التشغيل المباشر. تحقق من المتطلبات التالية:

  • يجب ألا تصل الخدمة إلى وحدة تخزين محمية ببيانات الاعتماد أثناء التشغيل في وضع التشغيل المباشر.
  • يجب ألا تحاول الخدمة استخدام مكونات، مثل Activities أو BroadcastReceivers أو Services أخرى لم يتم وضع علامة عليها بأنّها "مدركة للتشغيل المباشر" أثناء التشغيل في وضع التشغيل المباشر.
  • يجب أيضًا ألا تصل أي مكتبات تستخدمها الخدمة إلى وحدة تخزين محمية ببيانات الاعتماد أو تطلب المكونات غير المباشرةBootAware أثناء التشغيل في وضع التشغيل المباشر. ويعني هذا أنّ أي مكتبات يستخدمها التطبيق ويتم استدعاؤها من الخدمة يجب أن تكون على علم بالتمهيد المباشر، أو سيحتاج التطبيق إلى التحقق مما إذا كان يعمل في وضع التشغيل المباشر وعدم الاتصال به في هذا الوضع. على سبيل المثال، تعمل حِزم تطوير البرامج (SDK) لمنصة Firebase مع التشغيل المباشر (يمكن تضمينها في تطبيق بدون تعطله في وضع التشغيل المباشر)، ولكن العديد من واجهات برمجة تطبيقات Firebase لا يتيح طلبها في وضع التشغيل المباشر.
  • إذا كان التطبيق يستخدم Application مخصّصًا، يجب أن يكون Application أيضًا مزوَّدًا بميزة التشغيل بشكل مباشر (لا يمكن الوصول إلى وحدة تخزين بيانات الاعتماد المحمية في وضع التشغيل المباشر).

للحصول على إرشادات حول إرسال الرسائل إلى الأجهزة في وضع التشغيل المباشر، يُرجى الاطّلاع على إرسال رسائل تم تفعيل التشغيل المباشر بها.