تلقي الرسائل في تطبيق 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

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

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

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

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

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

تلقي رسائل FCM في وضع التمهيد المباشر

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

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

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

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

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

  1. في ملف Gradle على مستوى التطبيق، أضف تبعية إلى مكتبة دعم التمهيد المباشر FCM:

    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 الأخرى التي لم يتم وضع علامة عليها على أنها تدرك التمهيد المباشر أثناء التشغيل في وضع التمهيد المباشر.
  • يجب أيضًا ألا تتمكن أي مكتبات تستخدمها الخدمة من الوصول إلى التخزين المحمي ببيانات الاعتماد أو الاتصال بمكونات غير directBootAware أثناء التشغيل في وضع التمهيد المباشر. وهذا يعني أن أي مكتبات يستخدمها التطبيق والتي يتم استدعاؤها من الخدمة إما ستحتاج إلى أن تكون على علم بالتمهيد المباشر، أو سيحتاج التطبيق إلى التحقق مما إذا كان يعمل في وضع التمهيد المباشر وعدم الاتصال بها في هذا الوضع. على سبيل المثال، تعمل حزم Firebase SDK مع التمهيد المباشر (يمكن تضمينها في التطبيق دون تعطله في وضع التمهيد المباشر)، لكن العديد من واجهات برمجة تطبيقات Firebase لا تدعم استدعائها في وضع التمهيد المباشر.
  • إذا كان التطبيق يستخدم Application مخصصًا، فسيحتاج Application أيضًا إلى أن يكون على دراية بالتمهيد المباشر (لا يمكن الوصول إلى وحدة التخزين المحمية ببيانات الاعتماد في وضع التمهيد المباشر).

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