I followed the steps mentioned here.
Now, I'm receiving messages when app is in foreground via firebase.messaging().onMessage
and in the background via a headless task I defined according to the same guide, but I don't receive messages when the app is closed, however I get this warning in my android logcat
:
W GCM : broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10000000 pkg=com.mycustomapp (has extras) }
This is mybgMessaging.js
import firebase from 'react-native-firebase';
import type { RemoteMessage } from 'react-native-firebase';
export default async (message: RemoteMessage) => {
console.log("RemoteMessage", message);
const newNotification = new firebase.notifications.Notification()
.android.setSmallIcon(message.data.icon)
.android.setChannelId(message.data.channel_id)
.setNotificationId(message.messageId)
.setTitle(message.data.title)
.setBody(message.data.body)
.setData({
key1: 'value1',
key2: 'value2',
});
firebase.notifications().displayNotification(newNotification);
return Promise.resolve();
}
I've registered it as a headless task in my index.js
as follows:
import { AppRegistry } from 'react-native';
import App from './app';
import bgMessaging from './bgMessaging';
const app = new App();
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => bgMessaging);
These are the permissions I've enabled & the service:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="com.mycustomapp.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.mycustomapp.permission.C2D_MESSAGE" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
I can't figure out why am I not receiving messages when app is closed?
Is there something wrong with the way I've registered my headless task?
Am I missing some permission that I need for it to work?
P.S. I'm using react-native-navigation, and I wasn't sure how to register the headless task in it (if not the usual way as shown above).
Android
Build Tools: 27.0.3
React Native version: 0.53.3
RNFirebase Version: 4.2.0
Firebase Module: messaging
compileSdkVersion: 27
minSdkVersion: 16
targetSdkVersion: 26
@Ketn , try replacing const app = new App()
with AppRegistry.registerComponent('<app-name>', () => App)
, where <app-name>
is the name of the main component.
@aMarCruz Tried that, but now when the app is launched, it just shows a white screen. I don't think that is the issue.
@Ketn , I think Headless JS needs to be set in an earlier stage that your App class is instantiated.
What is it that your App exports?
It's an app similar to this: https://github.com/wix/react-native-navigation/tree/master/old-example-redux
How do I set Headless JS in an earlier stage?
@Ketn I see now... with wix navigation the initialization is diferent and I don't know how HeadlessJS is handled, it has multiple activities and different lifecycles.
The setup of my current project is like this, using react-navigation.
I expect it's done the way I've done. Not sure about that. I want to figure out if this is happening due to headlessJS implementation done wrong or something else. Because it's working fine when app is in the background (but not closed).
@Ketn I don't see any code of a channel being created, neither is a default channel mentioned in your manifest file. You won't be able to create any notifications without a channel post nougat I think.
if (Platform.OS !== "ios") {
notification.android
.setSmallIcon("ic_notification_icon")
.android.setChannelId("news");
const channel = new firebase.notifications.Android.Channel(
"news",
"News",
firebase.notifications.Android.Importance.Max
)
.setSound("notification_beep")
.setDescription("News channel");
await firebase.notifications().android.createChannel(channel);
}
@judemanutd Default channel exists in AndroidManifest.xml already. Must have missed putting it in while writing this post.
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
And I've tested on Android 5.1.1. This problem exists in all versions of android. For some reason, the headlessTask kills itself when the app is closed. Idk why though. Any way to figure out the reason?
@Ketn can you try it on an older device kitkat or below, I suspect this might be an issue with doze mode or battery optimizations.
Another thing you will want to check is if your app is added to autostart, this issue should only be there if you are using a phone that isn't stock android. Basically you need to goto the permission manager and add your app to autostart, sometimes restarting the device after doing so helps.
I created a library that brings up the autostart menu in a phone so the user will be able to add your app to autostart in production without having to search for the permission manager.
Using stock android. Notifications from all other apps work just fine.
@judemanutd I'm sorry, I just checked. It is due to battery optimization issue. I am using OnePlus 5T (android 8.1.0) and I went to the battery settings to set it in "Not Optimised" mode for my app and I'm receiving notifications just fine. However, all other apps are in Optimise mode by default too, yet I receive notifications from them properly. Is there any way to understand why is this happening, what can be done to fix this? Because I don't expect users to disable the default battery optimized state for my app by themselves.
@Ketn are you sending your notifications with priority high
@judemanutd Yes, I think so. I've tried sending both data-only and notification-only messages. Both have identical results (i.e. not working when app is killed and is in battery optimisation mode but working when in "not optimised" mode). This is the fcm message I send to fcm server from my server, in case you thin anything might be wrong with that?:
Data-only message
{
"data": {
"title":"App Notification",
"body":"This is to notify you",
"color":"#607D8B",
"channel_id":"test-channel",
"icon":"ic_notif",
"sound":"default",
"show_in_foreground":true
},
"to":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"priority":"high"
}
Notification message (I believe the default priority is high for notification messages?)
{
"to":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"time_to_live":660,
"notification": {
"title":"App Notification",
"body":"This is to notify you",
"android_channel_id":"test-channel"
}
}
Lemme know if anything's wrong with the above messages.
P.S. I get a successful response from Firebase upon sending those message requests even if I don't receive the notification on my device.
@Ketn Yep, everything looks correct, I am actually surprised that you are having issues with notification on messages because that is directly handled by the system and doesn't even start your app up, data messages are the ones where the system notifies your app.
About firebase giving a success on response, that is pretty much correct, firebase confirms that it received the message not that it was sent out from firebase servers.
I know that android P has introduced buckets for apps that throttle what an app can do and how it uses the phones resources https://developer.android.com/preview/features/power#buckets
A specific line in that says
More active apps are assigned to buckets that give the apps higher priority, making more system resources available to the app. In particular, the bucket determines how frequently the app's jobs run, how often the app can trigger alarms, and how often the app can receive high-priority Firebase Cloud Messaging (FCM) messages. These restrictions apply only while the device is on battery power; the system does not impose these restrictions on apps while the device is charging.
Again this is a P thing and not Oreo and considering a new app should be given high priority at the start I'm not entirely sure but maybe try it on a different device or plug your device in for charging and then test it.
@judemanutd I tried testing with device plugged in for charging. Still the same issue.
@Ketn , move the <service>
tags in your AndroidManifest.xml to inside <application>
@aMarCruz I'm sorry but I didn't mean to say that it's my Manifest file just the content of it that hold relevance. My service tags are obviously under application tag otherwise I wouldn't be receiving notifications etc. even when app is in foreground or background.
Slack app seems to have similar issues.
It seems to be due to battery optimization on android version 6 and later.
https://get.slack.help/hc/en-us/articles/360001562747-Known-issues-with-Android-notifications
I dont know if is it possible to force an app not to be battery optimized by android.
@Ketn unfortunately on OnePlus phones I don't think there is anything you can do from your app to prevent the behaviour you're seeing - it will require your users to disable battery optimization for your app. Notifications are highly reliable, except when device manufacturers interfere 馃檲
Here's a table for reference; taken from here:
Will close this issue as it's outside the realms of an issue with the library. Feel free to continue on the discussion here though if needed.
Loving react-native-firebase
and the support we provide? Please consider supporting us with any of the below:
React Native Firebase
and Invertase
on Twitter @Salakar - I understand that and setting "Don't Optimise" option helps but I also see apps like WhatsApp, Facebook, Twitter, etc. working fine without the "Don't Optimise" option enabled. I want to know why is that so. Is that random selection by the OS itself, based on app's battery usage or based on what criteria? Please give your input on that.
@Ketn I think that's due to whitelisting of apps by the OEM directly.
@Ketn change this:
{
"data": { // to notification, like this: "notitication" :{ ...
"title":"App Notification",
"body":"This is to notify you",
"color":"#607D8B",
"channel_id":"test-channel",
"icon":"ic_notif",
"sound":"default",
"show_in_foreground":true
},
"to":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"priority":"high"
}
and this on bgMessage.js
export default async (notification: Notification) => {
@Ketn I confirm that this is OS related. Opted for don't optimise and it worked. However, I am not sure if it is device dependent. I have a Oneplus 6 tho.
@Ketn unfortunately on OnePlus phones I don't think there is anything you can do from your app to prevent the behaviour you're seeing - it will require your users to disable battery optimization for your app. Notifications are highly reliable, except when device manufacturers interfere 馃檲
Here's a table for reference; taken from here:
Will close this issue as it's outside the realms of an issue with the library. Feel free to continue on the discussion here though if needed.
Loving
react-native-firebase
and the support we provide? Please consider supporting us with any of the below:
- 馃憠 Back financially via Open Collective
- 馃憠 Follow
React Native Firebase
andInvertase
on Twitter- 馃憠 Star this repo on GitHub 猸愶笍
Is this fixed in latest version?
I see an issue with Chrome (not firefox) but it doesn't have anything to do with the battery setting. And any running Chrome app will enable it to receive messages so be sure to test with no other running apps.
Most helpful comment
@judemanutd I'm sorry, I just checked. It is due to battery optimization issue. I am using OnePlus 5T (android 8.1.0) and I went to the battery settings to set it in "Not Optimised" mode for my app and I'm receiving notifications just fine. However, all other apps are in Optimise mode by default too, yet I receive notifications from them properly. Is there any way to understand why is this happening, what can be done to fix this? Because I don't expect users to disable the default battery optimized state for my app by themselves.