Flutter local notification didnt work on background
Flutter local notification didnt work on background in debug it is working fine. I have used this package for showing notifcation in foreground it works perfectly but on background it doesnt the firebase default notificatin is showing. Is there is a way to show local notificatin with action in background im attaching my code below
@pragma('vm:entry-point')
void onSelectNotification(NotificationResponse notificationResponse) async {
final payload = notificationResponse.payload;
if (payload != null && payload.isNotEmpty) {
Map<String, dynamic> data = Map<String, dynamic>.from(jsonDecode(payload));
log("Notification payload: ${data.toString()}");
String messageType = data['type'];
if (notificationResponse.actionId == 'accept_call') {
// Stop the audio first
await audioPlayer.stop();
audioPlayer.dispose();
// Cancel the notification
if (notificationId != null) {
flutterLocalNotificationsPlugin.cancel(notificationId!);
}
// Navigate to the call view
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (_) => CallView(
channelId: data['channelId'],
agoraToken: data['agora_token'],
contactName: data['caller_name'],
),
),
);
return; // Early return to prevent further execution
} else if (notificationResponse.actionId == 'reject_call') {
// Stop the audio first
await audioPlayer.stop();
audioPlayer.dispose();
// Cancel the notification
if (notificationId != null) {
flutterLocalNotificationsPlugin.cancel(notificationId!);
}
// Since this is a reject action, do not navigate to any page
log('Call Rejected');
return; // Early return to prevent further navigation
}
// Handle other message types based on 'messageType'
if (messageType == 'missed_call') {
BottomNavProvider().setPage(3);
} else if (messageType == 'chat') {
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (_) => IncomingCallView(
channelId: data['channelId'],
agoraToken: data['agora_token'],
contactName: data['channelId'],
),
),
);
} else if (messageType == 'new_interest') {
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (_) => IncomingCallView(
channelId: data['channelId'],
agoraToken: data['agora_token'],
contactName: data['caller_name'],
),
),
);
} else if (messageType == 'notification') {
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (_) =>
NotificationView(), // Navigate to the notification screen
),
);
}
} else {
log("Notification payload is null or empty.");
}
}
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
AudioPlayer audioPlayer = AudioPlayer();
int? notificationId;
class PushNoti {
String? _fcmToken;
final FirebaseMessaging _fcm = FirebaseMessaging.instance;
Future<void> requestNotificationPermission() async {
await _fcm.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
_fcmToken = await _fcm.getToken();
log('device FCM token is $_fcmToken');
LocalStorage.setString({'fcmToken': _fcmToken.toString()});
_fcmToken = await _fcm.getToken();
}
Future<void> initPushNotification() async {
_fcmToken = await _fcm.getToken();
log('device FCM token is $_fcmToken');
LocalStorage.setString({'fcmToken': _fcmToken.toString()});
// Handle incoming messages when the app is in the foreground
FirebaseMessaging.onMessage.listen((RemoteMessage? message) async {
// showNotification(message!);
// If it's a call type message, show the incoming call screen
if (message!.data.isNotEmpty && message!.data['type'] == 'call') {
audioPlayer.play();
navigatorKey.currentState
?.push(
MaterialPageRoute(
builder: (_) => IncomingCallView(
channelId: message!.data['channelId'],
agoraToken: message.data['agora_token'],
contactName: message.data['caller_name'],
),
),
)
.then((_) {
if (notificationId != null) {
audioPlayer.stop();
flutterLocalNotificationsPlugin.cancel(notificationId!);
}
});
} else {
showNotification(message);
}
});
// Handle notification taps when the app is in the background or terminated
FirebaseMessaging.onMessageOpenedApp
.listen((RemoteMessage? message) async {});
// Check if the app was opened from a terminated state due to a notification tap
_fcm.getInitialMessage().then((RemoteMessage? message) {});
}
}
void showNotification(RemoteMessage message) async {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
String? title = message.data['title'];
String? body = message.data['body'];
String? type = message.data['type'];
if (message.data['type'] == 'call') {
await audioPlayer.setAsset(
'assets/ringtone/ringtone.mp3'); // Load the ringtone from assets
audioPlayer.play();
log('hello world tttt ${message.data.toString()}');
}
var platformChannelSpecifics = NotificationDetails(
android: message.data['type'] == 'call'
? AndroidNotificationDetails(
'call_channel', // For call notifications
'Incoming Call',
importance: Importance.max,
priority: Priority.max,
// sound: RawResourceAndroidNotificationSound('isa_63861'), // Custom sound for calls (optional)
playSound: true,
color: UiColor.primary,
actions: <AndroidNotificationAction>[
AndroidNotificationAction(
'accept_call',
'Accept',
// icon: DrawableResourceAndroidBitmap("ic_accept"),
showsUserInterface: true,
),
AndroidNotificationAction(
'reject_call',
'Reject',
// icon: DrawableResourceAndroidBitmap("ic_reject"),
showsUserInterface: true,
),
],
)
: AndroidNotificationDetails(
'important_notifications', // For other notifications
'Important Notifications',
importance: Importance.high,
color: UiColor.primary,
// sound: RawResourceAndroidNotificationSound("notification_sound"), // Optional custom sound
actions: [], // No actions for other notifications (can be added dynamically)
),
iOS: DarwinNotificationDetails(
sound: 'default',
presentAlert: true,
presentBadge: true,
presentSound: true,
),
);
if (notification != null && android != null) {
notificationId = notification.hashCode;
flutterLocalNotificationsPlugin.show(notification.hashCode,
notification.title, notification.body, platformChannelSpecifics,
payload: jsonEncode(message.data));
}
}
Future<void> initLocalNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('mipmap/ic_launcher');
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: DarwinInitializationSettings(),
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveBackgroundNotificationResponse: (NotificationResponse notificationResponse) async {
// Handle background notification response here
log('Background notification received from local notoifction: ${notificationResponse.payload}');
},
onDidReceiveNotificationResponse: onSelectNotification);
}
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
// Show the notification first
showNotification(message);
// Check if the message type is 'call'
if (message.data['type'] == 'call') {
// Wait for 25 seconds
await Future.delayed(Duration(seconds: 25));
// Remove the notification after 25 seconds
flutterLocalNotificationsPlugin.cancel(message.notification.hashCode);
log('Notification removed after 25 seconds for call type.');
}
}
Future<void> firebaseMessagingForegroundHandler(RemoteMessage message) async {
if (message.data['type'] == 'call') {
await audioPlayer.setAsset(
'assets/ringtone/ringtone.mp3'); // Load the ringtone from assets
audioPlayer.play();
} else {
showNotification(message);
}
}
Could you please format the issue for better readability? It's all over the place right now.
same problem without solution.
Could you please format the issue for better readability? It's all over the place right now.
i have formatted can you please tell me why it doesnt show in background when notification triggers. Currently it shows the defautl firebase notification only and flutter local notifications only working in foreground
same problem without solution.
if you get any solution please mention I have tried many things
Anyone's got any workaround so far?
@BIBS23 I think you forgot something!
onDidReceiveBackgroundNotificationResponse: (NotificationResponse notificationResponse) async {
// Handle background notification response here
log('Background notification received from local notoifction: ${notificationResponse.payload}');
},
// Handle notification taps when the app is in the background or terminated
FirebaseMessaging.onMessageOpenedApp
.listen((RemoteMessage? message) async {});
You're not actually doing anything when your notifications are tapped. Please try to focus in on exactly what your problem is, and only show the code relevant to your problem, or close this issue if your problem is solved.
Maybe off topic but for me the ios notifications stopped working after updating firebase_messaging library to "15.1.4" or higher. (Android notifications were working ok). The flutter_local_notifications is updated to the latest version.
So i rolled backed firebase_messaging to version "15.1.3" and ios notifications started working again. Had a look at the changelog for firebase_messaging and they made changes in version "15.1.4".
So maybe worth trying to fix your firebase_messaging to "15.1.3" and see if your issue is solved. Just a thought....
@BIBS23 I've not integrated with FCM for a scenario like this but the reason why a local notification won't be shown when in the background in response to FCM is because you've configured it this way. Based on what you said, you're sending notification messages via FCM and FCM itself handles showing the notification when an app is in the background. In principle, you should be looking into using data messages so that your app is solely responsible on what it needs to do on receiving the message. This is something that would require you to look into from FCM and its SDK should provide callbacks for responding such messages in the background too