دریافت پیام در یک برنامه اندروید

اعلان‌های Firebase بسته به وضعیت پیش‌زمینه/پس‌زمینه برنامه دریافت‌کننده، رفتار متفاوتی دارند. اگر می‌خواهید برنامه‌های پیش‌زمینه پیام‌های اعلان یا پیام‌های داده را دریافت کنند، باید کدی بنویسید تا پاسخ تماس onMessageReceived را مدیریت کنید. برای توضیح تفاوت بین پیام‌های اعلان و داده، به انواع پیام مراجعه کنید.

رسیدگی به پیام ها

برای دریافت پیام، از سرویسی استفاده کنید که FirebaseMessagingService گسترش دهد. سرویس شما باید تماس‌های onMessageReceived و onDeletedMessages را لغو کند.

بسته به تأخیرهای پیش از تماس با onMessageReceived ، از جمله تأخیرهای سیستم عامل، زمان راه‌اندازی برنامه، مسدود شدن رشته اصلی توسط عملیات‌های دیگر، یا تماس‌های قبلی onMessageReceived که بیش از حد طولانی شده است، پنجره زمانی برای مدیریت یک پیام ممکن است کمتر از 20 ثانیه باشد. پس از آن زمان، رفتارهای مختلف سیستم عامل مانند حذف فرآیند اندروید یا محدودیت های اجرای پس زمینه اندروید 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 نماد برنامه را به رنگ سفید نمایش می‌دهد.

لغو 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() دریافت کنید، زمانی که نمونه برنامه این پاسخ تماس را دریافت می کند، باید یک همگام سازی کامل با سرور برنامه شما انجام دهد. اگر در 4 هفته گذشته پیامی برای برنامه در آن دستگاه ارسال نکرده باشید، FCM با onDeletedMessages() تماس نخواهد گرفت.

پیام‌های اعلان را در یک برنامه پس‌زمینه مدیریت کنید

وقتی برنامه شما در پس‌زمینه است، Android پیام‌های اعلان را به سینی سیستم هدایت می‌کند. با ضربه زدن کاربر روی اعلان، راه‌انداز برنامه به‌طور پیش‌فرض باز می‌شود.

این شامل پیام‌هایی می‌شود که هم شامل اعلان و هم بار داده (و همه پیام‌های ارسال شده از کنسول اعلان‌ها) هستند. در این موارد، اعلان به سینی سیستم دستگاه تحویل داده می‌شود و محموله داده‌ها بر اساس هدف فعالیت راه‌انداز شما تحویل داده می‌شود.

برای اطلاعات بیشتر در مورد تحویل پیام به برنامه خود، به داشبورد گزارش FCM مراجعه کنید، که تعداد پیام‌های ارسال شده و باز شده در دستگاه‌های Apple و Android را به همراه داده‌های «impressions» (اعلان‌هایی که کاربران مشاهده می‌کنند) را برای برنامه‌های 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. با افزودن ویژگی android:directBootAware="true" در مانیفست برنامه، بوت مستقیم FirebaseMessagingService برنامه را آگاه کنید:

    <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 با راه‌اندازی مستقیم کار می‌کند (آنها را می‌توان در یک برنامه قرار داد بدون اینکه در حالت راه‌اندازی مستقیم از کار بیفتد)، اما بسیاری از APIهای Firebase از فراخوانی در حالت راه‌اندازی مستقیم پشتیبانی نمی‌کنند.
  • اگر برنامه از یک Application سفارشی استفاده می‌کند، Application همچنین باید از راه‌اندازی مستقیم آگاه باشد (عدم دسترسی به فضای ذخیره‌سازی حفاظت شده اعتبار در حالت بوت مستقیم).

برای راهنمایی در مورد ارسال پیام به دستگاه‌ها در حالت راه‌اندازی مستقیم، به ارسال پیام‌های فعال بوت مستقیم مراجعه کنید.