اعلانهای Firebase بسته به وضعیت پیشزمینه/پسزمینه برنامه دریافتکننده، رفتار متفاوتی دارند. اگر میخواهید برنامههای پیشزمینه پیامهای اعلان یا پیامهای داده را دریافت کنند، باید کدی بنویسید تا پاسخ تماس onMessageReceived
را مدیریت کنید. برای توضیح تفاوت بین پیامهای اعلان و داده، به انواع پیام مراجعه کنید.
رسیدگی به پیام ها
برای دریافت پیام، از سرویسی استفاده کنید که FirebaseMessagingService
گسترش دهد. سرویس شما باید تماسهای onMessageReceived
و onDeletedMessages
را لغو کند.
onMessageReceived
برای اکثر انواع پیام، با استثنائات زیر ارائه شده است:
پیامهای اعلان زمانی که برنامه شما در پسزمینه است ارسال میشود . در این حالت اعلان به سینی سیستم دستگاه تحویل داده می شود. ضربه زدن کاربر روی یک اعلان، راهانداز برنامه را بهطور پیشفرض باز میکند.
پیامهایی با اعلان و بار داده، وقتی در پسزمینه دریافت میشوند . در این حالت، اعلان به سینی سیستم دستگاه تحویل داده میشود و محموله دادهها در موارد اضافی هدف فعالیت راهانداز شما تحویل داده میشود.
به طور خلاصه:
وضعیت برنامه | اطلاع رسانی | داده ها | هر دو |
---|---|---|---|
پیش زمینه | onMessageReceived | onMessageReceived | onMessageReceived |
پس زمینه | سینی سیستم | onMessageReceived | اعلان: سینی سیستم داده: در موارد اضافی قصد. |
پاسخ تماس onMessageReceived
دارای وقفه هایی است که به شما امکان می دهد به سادگی یک اعلان ارسال کنید، اما تایمرها طوری طراحی نشده اند که به برنامه اجازه دسترسی به شبکه یا انجام کارهای اضافی را بدهد. به این ترتیب، اگر برنامه شما کار پیچیده تری انجام می دهد، باید کارهای بیشتری انجام دهید تا مطمئن شوید که برنامه می تواند کار خود را کامل کند.
اگر انتظار دارید برنامه شما نزدیک به 10 ثانیه برای مدیریت یک پیام نیاز داشته باشد، باید یک کار WorkManager را برنامه ریزی کنید یا دستورالعمل WakeLock زیر را دنبال کنید. در برخی موارد، بسته به تأخیرهای پیش از تماس onMessageReceived
، از جمله تأخیرهای سیستم عامل، زمان راهاندازی برنامه، مسدود شدن رشته اصلی توسط عملیاتهای دیگر، یا تماسهای قبلی onMessageReceived
که بیش از حد طولانی میشوند، پنجره زمانی برای مدیریت پیام ممکن است کمتر از 10 ثانیه باشد. پس از انقضای آن تایمر، برنامه شما ممکن است در معرض محدودیتهای کشتن فرآیند یا اجرای پسزمینه باشد. به خاطر داشته باشید که تاخیر برای تراکنشهای شبکه و راهاندازی برنامهها میتواند قابل توجه باشد، بنابراین در صورت شک، برنامهریزی کنید که پردازش پیامتان طولانی شود، اگر وابستگیهای ناهمزمانی مانند دسترسی به شبکه یا الزامات بارگیری شدید داده وجود دارد.
مانیفست برنامه را ویرایش کنید
برای استفاده از 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
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. }
هنگام مدیریت پیام های FCM، دستگاه را بیدار نگه دارید
اگر برنامه شما باید هنگام پردازش یک پیام FCM دستگاه را بیدار نگه دارد، در این زمان باید WakeLock را نگه دارد یا باید یک کار WorkManager ایجاد کند. WakeLocks برای فعالیتهای پردازش کوتاهی که ممکن است از مهلت زمانی پیشفرض onMessageReceived
فراتر رود، به خوبی کار میکند. برای گردشهای کاری گسترده، مانند ارسال چندین RPC سریال به سرورهای شما، استفاده از کار WorkManager مناسبتر از WakeLock است. در این بخش بر روی نحوه استفاده از WakeLocks تمرکز می کنیم. WakeLock از خوابیدن دستگاه در حین اجرای برنامه جلوگیری میکند، که میتواند منجر به افزایش مصرف باتری شود، بنابراین استفاده از WakeLocks باید برای مواردی که برنامه شما نباید در هنگام مدیریت پیام متوقف شود، رزرو شود، مانند:
- اعلان هایی به کاربر که به زمان حساس هستند.
- فعل و انفعالات با یک دستگاه خاموش که نباید قطع شود (مانند انتقال شبکه یا ارتباطات با دستگاه دیگر، مانند ساعت جفت شده).
ابتدا باید مطمئن شوید که برنامه شما مجوز WakeLock را درخواست میکند (FCM SDK به طور پیشفرض این مورد را شامل میشود، بنابراین معمولاً نیازی به اضافه کردن چیزی نیست).
<uses-permission android:name="android.permission.WAKE_LOCK" />
سپس برنامه شما باید در ابتدای فراخوانی FirebaseMessagingService.onMessageReceived()
یک WakeLock دریافت کند و در پایان تماس آن را آزاد کند.
FirebaseMessagingService
سفارشی برنامه:
@Override public void onMessageReceived(final RemoteMessage message) { // If this is a message that is time sensitive or shouldn't be interrupted WakeLock wakeLock = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK, "myApp:messageReceived"); try { wakeLock.acquire(TIMEOUT_MS); // handle message ... finally { wakeLock.release(); } }
لغو 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 استفاده کند.
مدیریت پیام حالت بوت مستقیم را در برنامه خود فعال کنید
در فایل Gradle در سطح برنامه، یک وابستگی به کتابخانه پشتیبانی مستقیم بوت FCM اضافه کنید:
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
با افزودن ویژگی
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
همچنین باید از راهاندازی مستقیم آگاه باشد (عدم دسترسی به فضای ذخیرهسازی حفاظت شده اعتبار در حالت بوت مستقیم).
برای راهنمایی در مورد ارسال پیام به دستگاهها در حالت راهاندازی مستقیم، به ارسال پیامهای فعال بوت مستقیم مراجعه کنید.