I am working on a Flutter app. I need to integrate notifications using firebase cloud messaging. I am able to send notifications both in foreground and background. But, in case of background, the onLaunch and onResume are not getting triggered.
This is my JSON notification object:
{
"sound": "default",
"registration_ids": userToken,
"collapse_key": "type_b",
"priority": "high",
"notification": {
"title": 'New message',
"body": messageContent,
},
"data": {
"type": "message",
"title": 'New message',
"body": messageContent,
"click_action": "FLUTTER_NOTIFICATION_CLICK",
}
}
And here is the code for all the callbacks:
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage called");
if (message['data']['type'] == 'message') {
print(message['data']['type']);
setState(() {
newMessage = true;
});
}
},
onLaunch: (Map<String, dynamic> message) async {
print('onlaunch called');
// open message screen
},
onResume: (Map<String, dynamic> message) async {
print('onResume called');
// open message screen
},
);
I am getting this log when the app is in background:
W/FirebaseMessaging(12077): Notification Channel set in AndroidManifest.xml has not been created by the app. Default value will be used.
E/FirebaseMessaging(12077): Notification pending intent canceled
But the channel id is already set in AndroidManifest.xml
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="#string/default_notification_channel_id"/>
And intent-filter is there too:
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
I don't know what I am missing here. Any help is would be great. Thank you!
Add the below code in AndroidManifest.xml. Don't delete the other one just add this one.
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Related
When I send firebase cloud message, I touched the notification message in background of android device.
but app was not launched.
even if I set the click_action, and intent-filter in Manifest file.
I dont know what problem is.
I just want to launch app when I touch background push notification . but even if I touched background push notification, no launch the app
send message
{
"message": {
"android": {
"data": {
"scheme": "",
"payload": "null",
"background": "false",
"userId": "userId"
},
"notification": {
"body": "sdf",
"click_action": "DeepLinkHandlerActivity",
"default_light_settings": true,
"default_sound": true,
"default_vibrate_timings": true,
"title": "test"
}
},
"apns": {
"payload": {
"aps": {
"alert": {
"body": "sdf",
"title": "test"
},
"badge": 1,
"sound": "default"
}
}
},
"data": {
"scheme": "",
"payload": "null",
"userId": "b8ebe243-7d3b-41d8-b986-6abcb0fbdebf",
"background": "false"
},
"notification": {
"body": "sdf",
"title": "test"
},
"token": "tokendata"
}
}
Manifestfile
<activity
android:name=".ui.activity.login.SplashActivity"
android:label="#string/app_name"
android:exported="false"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="DeepLinkHandlerActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
service in manifest file
<service
android:name=".firebase.MyFirebaseMessagingService"
android:exported="false"
android:directBootAware="true"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
did you create a service named FirebaseMessagingService or similarly named? if you have created it, you need to create intent and PendingIntent there and add it. If you do not have such a service, you need to prepare the service. While researching for you, I found a convenient example; https://www.geeksforgeeks.org/how-to-push-notification-in-android-using-firebase-cloud-messaging/
FirevaseMessagingService.kt source file
remoteMessage.notification?.let { notification ->
Log.d(CONST.LOG_DEBUG, "click action ${notification.clickAction}")
if(!notification.title.isNullOrEmpty()) {
val pattern = longArrayOf(100, 500, 100, 500, 100, 700)
var intent = Intent(this#MyFirebaseMessagingService, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("badge_count", 1)
//intent.putExtra("scheme", remoteMessage.data["scheme"])
if(remoteMessage.data != null) {
val scheme = remoteMessage.data["scheme"]
scheme?.let {
if(it.startsWith("WEBVIEW")) {
val url = it.split("_")[1]
intent = Intent(this#MyFirebaseMessagingService, MainActivity::class.java)
intent.putExtra("url", url)
intent.putExtra("scheme", it)
} else if(it.startsWith("TECHPOST")) {
val id = it.split("_")[1]
intent = Intent(this#MyFirebaseMessagingService, TechPostDetailActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("scheme", it)
} else if(it.startsWith("HOTCLIP")) {
val id = it.split("_")[1]
intent = Intent(this#MyFirebaseMessagingService, HotClipDetailActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("scheme", it)
} else if(it.startsWith("NOTICE")) {
val id = it.split("_")[1]
intent = Intent(this#MyFirebaseMessagingService, NotificationDetailActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("scheme", it)
} else {
}
}
}
val mPendingIntent = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
var builder = NotificationCompat.Builder(this , "default")
builder.setFullScreenIntent(mPendingIntent , true)
builder.setSmallIcon(R.mipmap.appicon)
builder.setContentTitle(remoteMessage.notification?.title)
builder.setContentText(remoteMessage.notification?.body)
//builder.setColor(Color.BLUE)
builder.setAutoCancel(true)
builder.setContentIntent(mPendingIntent)
builder.setVibrate(pattern)
val notificationManager: NotificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(NotificationChannel("default" , "default_channel" , NotificationManager.IMPORTANCE_DEFAULT))
}
notificationManager.notify(1 , builder.build())
}
}
I examined the codes and there are 2 types of messages in Google Firebase Messaging, one of them is "notification" and the other is "data" and you have done data control on the code. How do you send the notification when you send it? Notification can be sent through the firebase panel, but the data message is sent only through the server. When sending a message, you need to check which of the "Notification" - "Data" you are sending. In the "Notification" notifications, the codes you wrote while the application is in the kill state will not work, but if you send a "Data" notification, the codes you wrote when the application is killed will also work. Therefore, if the notification you sent is "Notification", you need to change it to "Data". As I said, "Data" Notifications cannot be sent through the Panel, they are only sent from the server.
Firebase push notification is working fine for all three states of app: foreground, background, killed.
But notification not delivered if device is idle for few minutes and no charging state.
However on charging push notification is working no matter how long idle time is.
I have tried with:
disabling 'Power saving mode'.
disabling 'Adaptive power saving mode'.
battery optimization for app.
added in manifest
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
removed [android:exported="false"] from
<service
android:name="firebase.MyFirebaseMessagingService" =>[android:exported="false"]>
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
{
"registration_ids": [
"ei0....ySI"
],
"data": {
"priority" : "high",
"title": "msg title",
"body": "msg body"
},
"android": {
"priority": "high"
},
"apns": {
"headers": {
"apns-priority": "10"
}
},
"webpush": {
"headers": {
"Urgency": "high"
}
}
}
Moving "priority": "high" to the root worked.
Now payload is like:
{
"registration_ids": ["cWy......FrN"],
"data": {
"title": "this is msg title",
"body": "this is msg body"
},
"priority": "high"
}
I need to make an Android app where the user can receive notifications whenever I send them in the Firebase Cloud Messaging console. I am building it with Flutter.
I have gone through all the setup and I think the app is correctly connecting to Firebase, because there are no error logs.
However, when I send messages via Firebase, my app (which is running on local emulator) doesn't show any notifications.
This is the code of my app.
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:joves_lectors/webview_container.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<void> initFirebaseMessaging() async {
print(await FirebaseMessaging.instance.getInitialMessage());
FirebaseMessaging.onMessage.listen((message) {
if(message.notification != null) {
print(message.notification.body);
print(message.notification.title);
}
});
}
#override
void initState() {
super.initState();
print(FirebaseMessaging.instance.pluginConstants);
print(FirebaseMessaging.instance.isSupported());
initFirebaseMessaging();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Text("Hello")//WebViewContainer("https://jornades.joveslectors.cat"),
);
}
}
If I go to the Firebase console and send a Cloud Message notification, nothing happens. I've been trying to debug the problem, but I don't know how I can check that my app is connected to Firebase Messaging. I don't get any error messages. This is what my console prints:
I/flutter ( 7980): {AUTO_INIT_ENABLED: true}
I/flutter ( 7980): true
I/flutter ( 7980): null
I don't know if I am missing any steps or making any mistake with my code.
These are my dependencies:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
webview_flutter: ^2.0.9
firebase_core: ^1.3.0
firebase_messaging: ^10.0.2
flutter_local_notifications: ^6.0.0
i) So you must have to add this below code just before this tag </activity> in your android/app/src/main/androidManifest.xml file
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
ii) Also add this meta data just before the </application> tag
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="default_notification_channel_id" />
iii) so when you sends the push notification you must pass the FLUTTER_NOTIFICATION_CLICK in your body in json request like the below request
{
"to":"-----YOUR SERVER KEY -------",
"notification" : {
"sound" : "default",
"body" : "test body",
"title" : "test title",
"content_available" : true,
"priority" : "high"
},
"data" : {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"sound" : "default",
"body" : "test body",
"title" : "test title",
"content_available" : true,
"priority" : "high"
}
}
I hope this solves your problem
I've used react-native-fcm for remote notification in android and iPhone.
react-native-fcm
In Android foreground I'm not be able to getting remote notification in notification bar.
In background mode I'm able to getting notification successfully but some how in foreground doesn't.
Android Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nusape">
<application>
<receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/>
<receiver android:enabled="true" android:exported="true" android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#mipmap/ic_launcher"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="my_default_channel"/>
<service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<activity android:launchMode="singleTop" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="fcm.ACTION.HELLO" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
App.js
async componentDidMount() {
// create NotificationChannel for future use!
FCM.createNotificationChannel({
id: 'my_default_channel',
name: 'Default',
description: 'used for example',
priority: 'high'
});
// initially user get InitialNotification frim the app if any pending
FCM.getInitialNotification().then(notif => {
console.log("getInitialNotification Notification : => ", notif);
// if notif.targetScreen is details screen then it will redirect to details screen directly!
if (notif && notif.targetScreen === "detail") {
setTimeout(() => {
this.props.navigation.navigate("Detail");
}, 500);
}
});
// added notification listener for getting any notification called below function then
this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => {
console.log("FCMEvent.Notification Notification : => ", notif);
if (Platform.OS === 'ios' && notif._notificationType === NotificationType.WillPresent && !notif.local_notification) {
notif.finish(WillPresentNotificationResult.All);
return;
}
// if user tap to notification bar then open app then below condition will follow up and redirect to details screen!
if (notif.opened_from_tray) {
if (notif.targetScreen === 'detail') {
setTimeout(() => {
navigation.navigate('Detail')
}, 500)
}
setTimeout(() => {
alert(`User tapped notification\n${JSON.stringify(notif)}`)
}, 500)
}
// check whether app is in background or foreground for generate notification
if (AppState.currentState !== 'background'){
this.showLocalNotification(notif);
});
// getting user permission for sending notification or not ?
try {
let result = await FCM.requestPermissions({
badge: true,
sound: true,
alert: true
});
console.log("Notification requestPermissions : => ", result)
} catch (e) {
console.error(e);
}
// Generating token for particular user wise send notification
FCM.getFCMToken().then(token => {
FCM.subscribeToTopic("channelToTopic");
console.log("Notification token : => ", token);
this.setState({ token: token || "" });
});
// Get APNSTOKEN for only ios
if (Platform.OS === "ios") {
FCM.getAPNSToken().then(token => {
console.log("APNS TOKEN (getFCMToken)", token);
});
}
}
// show notification when app is in foreground and getting any new notification
showLocalNotification = (notif) => {
FCM.presentLocalNotification({
channel: 'my_default_channel',
id: new Date().valueOf().toString(),
title: notif.fcm.title,
body: notif.fcm.body,
priority: "high",
badge: 1,
number: 1,
ticker: "My Notification Ticker",
auto_cancel: true,
big_text: "Show when notification is expanded",
sub_text: "This is a subText",
wake_screen: true,
group: "group",
icon: "ic_launcher",
ongoing: true,
my_custom_data: "my_custom_field_value",
lights: true,
show_in_foreground: true
});
};
I'm suffering this issue from last 2 months and not get it well solution for the same as i doing so many new attempt to resolve issue but at the end not getting any succeed.
According to the official Github of
react-native-fcm,
this library is depreciated.
You can use the
react-native-firebase
for generating notification.
I was able to get the notifications working in about 2 hours for android.
If you want the code I can share it.
good luck.
Update - Sorry I couldn't answer earlier because of my office account.
This is my code for showing android foreground notifications.
firebase.messaging()
.subscribeToTopic(this.state.user.user_name)
.then(response => console.log('response from FCM TOPIC' + response))
.catch(error => console.log('error from FCM TOPIC'+ error));
this.notificationListener = firebase.notifications().onNotification(notification => {
let notificationMessage = notification._android._notification._data.action;
let recordId = notification._android._notification._data.recordID;
let { title, body } = notification;
// console.log('ttttt', notification)
// notification.android.setAutoCancel(false)
console.log(title, body, notificationMessage, recordId);
const channelId = new firebase.notifications.Android.Channel(
'Default',
'Default',
firebase.notifications.Android.Importance.High
);
firebase.notifications().android.createChannel(channelId);
let notification_to_be_displayed = new firebase.notifications.Notification({
data: notification._android._notification._data,
sound: 'default',
show_in_foreground: true,
title: notification.title,
body: notification.body,
});
if (Platform.OS == 'android') {
notification_to_be_displayed.android
.setPriority(firebase.notifications.Android.Priority.High)
.android.setChannelId('Default')
.android.setVibrate(1000);
}
console.log('FOREGROUND NOTIFICATION LISTENER: \n', notification_to_be_displayed);
firebase.notifications().displayNotification(notification_to_be_displayed);
});
As per the library issues listed here you can try two things:
just pass show_in_foreground in your data property in remote notification
android shows notification only when app state is killed or background. To display notifications in app foreground, you need to show local notification.
Sample code:
FCM.on(FCMEvent.Notification, notif => {
if (!notif.opened_from_tray) {
showLocalNotification();
}
});
showLocalNotification() {
FCM.presentLocalNotification({
id: new Date().valueOf().toString(), // (optional for instant notification)
title: "Test Notification with action", // as FCM payload
body: "Force touch to reply", // as FCM payload (required)
show_in_foreground: true // notification when app is in foreground (local & remote)
});
}
Full code is here
Which API level you are testing on ? Android API 26 and above requires channels to be created in order to receive notifications in foreground. please read this for more information.
react-native-fcm is also updated to include channels too, refer this
though the library should not be used anymore as the library is not maintained anymore, a good alternative is react-native-firebase.
Im using react-native-firebase in my app for cloud messanging + notification. it get all body and data when app is in use but it cant get anything when app is closed or in background ....
I tried Headless JS but thats also not working
when i click on notification and when it open's the app its shows this {"google.priority":"high"}
thnaks in advance....
this is my android mainfest
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:allowBackup="false"
android:theme="#style/AppTheme"
android:largeHeap="true">
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!---firebase -->
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- <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.RNFirebaseBackgroundMessagingService" />
<!---firebase end-->
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
this is my componentdidmount() function
async componentDidMount() {
this.getValueLocally();
requestCameraLOCATION()
const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const action = notificationOpen.action;
const notification: Notification = notificationOpen.notification;
var seen = [];
alert(JSON.stringify(notification.data, function(key, val) {
if (val != null && typeof val == "object") {
if (seen.indexOf(val) >= 0) {
return;
}
seen.push(val);
}
return val;
}));
}
const channel = new firebase.notifications.Android.Channel('test-channel', 'Test Channel', firebase.notifications.Android.Importance.Max)
.setDescription('My apps test channel');
// Create the channel
firebase.notifications().android.createChannel(channel);
this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
// Process your notification as required
// ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
});
this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
// Process your notification as required
notification
.android.setChannelId('test-channel')
.android.setSmallIcon('ic_launcher');
firebase.notifications()
.displayNotification(notification);
});
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
var seen = [];
alert(JSON.stringify(notification.data, function(key, val) {
if (val != null && typeof val == "object") {
if (seen.indexOf(val) >= 0) {
return;
}
seen.push(val);
}
return val;
}));
firebase.notifications().removeDeliveredNotification(notification.notificationId);
});
}
async checkPermission() {
firebase.messaging().hasPermission()
.then(enabled => {
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
});}
async getToken() {
let fcmToken = await AsyncStorage.getItem('fcmToken');
if (!fcmToken) {
fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
// user has a device token
await AsyncStorage.setItem('fcmToken', fcmToken);
}
}
}
async requestPermission() {
firebase.messaging().requestPermission()
.then(() => {
this.getToken();
})
.catch(error => {
console.warn(error);
});
}
and this is my bgMessaging.js
import firebase from 'react-native-firebase';
import type { RemoteMessage } from 'react-native-firebase';
import type { Notification,NotificationOpen} from 'react-native-firebase';
export default async (message: RemoteMessage) => {
const newNotification = new firebase.notifications.Notification()
.android.setChannelId(message.data.channelId)
.setNotificationId(message.messageId)
.setTitle(message.data.title)
.setBody(message.data.body)
.setSound("default")
.setData(message.Data)
.android.setAutoCancel(true)
.android.setSmallIcon('ic_notification')
.android.setCategory(firebase.notifications.Android.Category.Alarm)
// Build a channel
const channelId = new firebase.notifications.Android.Channel(message.data.channelId, channelName, firebase.notifications.Android.Importance.Max);
// Create the channel
firebase.notifications().android.createChannel(channelId);
firebase.notifications().displayNotification(newNotification)
return Promise.resolve();
}
there are two types of messages:
notification + data messages that will be handled by the FCM while in the background (so your code will not have access to the notification), and will call onNotification while in the foreground,
data-only messages will call headlessjs while in the background/closed and will call onMessage while in the foreground.
note: if you remove the title and body, your message will be categorized as the second one. also, data is optional in the first category.
to recap:
for data-only messages:
App in foreground : onMessage triggered
App in background/App closed : Background Handler (HeadlessJS)
for notification + data messages:
App in foreground : onNotification triggered
App in background/App closed : onNotificationOpened triggered if the notification is tapped
for more information and for iOS read the official docs for data-only messages and notification+data messages
It seems that RN firebase did not support this functionality on Android.
Please refer below:
https://rnfirebase.io/docs/v5.x.x/notifications/receiving-notifications#4)-Listen-for-a-Notification-being-opened
On Android, unfortunately there is no way to access the title and body of an opened remote notification. You can use the data part of the remote notification to supply this information if it's required.