Flutter local notification doesn't work and gives me PlatformException - flutter

I am trying to show notifications in my Flutter app but I am getting this exception:
Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
this is the method I'm using. How can I fix it?
void sendNotification({String? title, String? body}) async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
const IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
);
flutterLocalNotificationsPlugin.show(
0,
title,
body,
const NotificationDetails(
android:
AndroidNotificationDetails(
'channel id',
'channel',
'channel description',
importance: Importance.max
)),
);
}

Related

Flutter_local_notifications notificationResponse.payload is always empty string,

I'm trying to setup my mobile app, so that when a user gets a FCM message, when they click on it, I can use data within the message to route them to appropriate screen.
My FCM message looks like this:
const fcmMessage = {
notification: {
title: title,
body: message
},
data:{
type:'Chat',
Name: 'Mike',
body:'test'
},
android: {
notification: {
title:title,
body: message,
channel_id:'high_importance_channel'
}
},
token: msgToken,
};
then within my main() method, I am initializing the Flutter_Local_notifications as per the code snippet below.
The issue is when I click on the notification, the payload is always an empty string?
These are the code lines that perform this. Why is the NotificationResponse.payload empty string?
ultimately, I need access the "data" object in the FCM message.
void onDidReceiveNotificationResponse(NotificationResponse notificationResponse) async {
print(notificationResponse.payload);
}
Here is the full main() method.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// Set the background messaging handler early on, as a named top-level function
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title/
importance: Importance.high,
);
}
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOs = DarwinInitializationSettings();
var initSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
void onDidReceiveNotificationResponse(NotificationResponse notificationResponse) async {
print(notificationResponse.payload);
}
await flutterLocalNotificationsPlugin.initialize(initSettings,onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,);
/// Create an Android Notification Channel.
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
FlutterLocalNotificationsPlugin s = FlutterLocalNotificationsPlugin();
s.show(
notification.hashCode,
notification?.title,
notification?.body,
NotificationDetails(
android: AndroidNotificationDetails(channel.id, channel.name,
icon: 'launch_background',
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.high,
ongoing: true,
styleInformation: BigTextStyleInformation('')),
),
);
}
});
runApp(MyApp());
}
UPDATE, found what I needed. In the LocalNotification show method, we can add the payload attribute and set it to whatever part of the message.
For my use case, I encode the message.data , and then in the didReceive method, I can decode back to JSON object and use as needed.
s.show(
payload: jsonEncode(message.data),
notification.hashCode,
notification?.title,
notification?.body,
NotificationDetails(
android: AndroidNotificationDetails(channel.id, channel.name,
icon: 'launch_background',
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.high,
ongoing: true,
styleInformation: BigTextStyleInformation('')),
),
);

How to navigate from the local local notification from the background?

I am using flutter local notification in my application. I could not able to navigate to a specific page by clicking the local notification when the application is in background.
It gives me the error:
_AssertionError ('package:flutter_local_notifications/src/platform_flutter_local_notifications.dart': Failed assertion: line 1018 pos 12: 'callback != null': The backgroundHandler needs to be either a static function or a top
level function to be accessible as a Flutter entry point.)
This is my code:
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> listiningToNotification() async {
FirebaseMessaging.onMessageOpenedApp
.listen((message) => notificationOnClick(message));
}
Future<void> localNotification(RemoteMessage message) async {
AndroidNotificationChannel channel = AndroidNotificationChannel(
"local_notification",
message.data["booking_id"],
description: message.data["task_id"],
importance: Importance.max,
playSound: true,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings("#drawable/notification_icon");
const InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (details) => notificationOnClick(message),
onDidReceiveBackgroundNotificationResponse: (details) =>
firebaseMessagingBackgroundHandler,
);
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(channel.id, channel.name,
channelDescription: channel.description,
importance: channel.importance,
playSound: channel.playSound,
color: Colors.white),
),
payload: notification.body);
}
}
#pragma('vm:entry-point')
Future<void> localNotificationBackground(
{required NotificationResponse details}) async {
print(details.payload);
}
What I am doing wrong or what I am missing ?
I also have this function for the firebase background notification. Is this the reason ?
#pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
List<FirebaseApp> app = Firebase.apps;
if (app.length < 2) {
await Firebase.initializeApp(
name: "xxxxxxxxxx", options: DefaultFirebaseOptions.currentPlatform);
}
FirebaseMessaging messaging = FirebaseMessaging.instance;
await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: true,
criticalAlert: false,
provisional: true,
sound: true,
);
}

add multiple scheduled notifications using flutter

I've been working on an adhan app using flutter and I'm working on the scheduled notification using flutter_local_notifications package. Using the .zonedSchedule I can only display notification once.
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings("icon");
IOSInitializationSettings iosInitializationSettings = IOSInitializationSettings();
final InitializationSettings initializationSettings = InitializationSettings(
android: androidInitializationSettings,
iOS: iosInitializationSettings);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
and for the Notification detail
var android = AndroidNotificationDetails(
"$id", channel,
importance: Importance.max,
sound: RawResourceAndroidNotificationSound('adhan'),
playSound: true,
);
var ios = IOSNotificationDetails();
var platform = NotificationDetails(android: android, iOS: ios);
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
and used it as
_flutterLocalNotificationsPlugin.zonedSchedule(
1,
"title",
"dhuhr",
tz.TZDateTime.from(prayerTimes.dhuhr!, location),
platform,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation
.absoluteTime,
androidAllowWhileIdle: true,
matchDateTimeComponents: DateTimeComponents.time
);
_flutterLocalNotificationsPlugin.zonedSchedule(
2,
"title",
"Asr",
tz.TZDateTime.from(prayerTimes.asr!, location),
platform,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation
.absoluteTime,
androidAllowWhileIdle: true,
matchDateTimeComponents: DateTimeComponents.time
);
the problem I'm facing is that if the time matches with the current prayer time it works fine. but when it's time for the next schedule it doesn't display anything.
So how can I display notification multiple times in a day?

Sound and pop-up notifications do not work in flutter

I am using local_notifications plugin in my android flutter app. I do everything according to the documentation and the notifications work but without sound and pop-up windows. Importance and priority set to max. Maybe the reason is in some settings of my phone or its OS (MIUI Global 11.0.3, Android 9 PKQ1)?
Notification code:
FlutterLocalNotificationsPlugin notificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> initNotificationPlugin() async {
const AndroidInitializationSettings androidSettings =
AndroidInitializationSettings('ic_launcher');
final IOSInitializationSettings iosSettings =
IOSInitializationSettings();
final initSettings =
InitializationSettings(android: androidSettings, iOS:
iosSettings);
await notificationsPlugin.initialize(initSettings);
}
void showNotification(String title, String body,
DateTime dateTime, int id) async {
var androidDetails = AndroidNotificationDetails(
'notificationChannel', 'channel', 'description',
importance: Importance.max,
priority: Priority.max,
playSound: true,
showWhen: false,
enableVibration: true);
var iosDetails = IOSNotificationDetails();
var details = NotificationDetails(android: androidDetails, iOS:
iosDetails);
await notificationsPlugin.zonedSchedule(
id,
title,
body,
timezone.TZDateTime.from(
dateTime, timezone.getLocation('Europe/Moscow')),
details,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}

flutter_local_notifications not working on ios, but working on android

If I use the show() method of the FlutterLocalNotificationsPlugin then I get a notification on Android but not on ios.
showNotification(
String notificationId, String title, String body, String payload) async {
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
"important-notifications",
tr("DEVICE.IMPORTANT_NOTIFICATIONS_NAME"),
tr("DEVICE.IMPORTANT_NOTIFICATIONS_DESCRIPTION"),
importance: Importance.max,
priority: Priority.high,
ledColor: Colors.pink,
ledOffMs: 50,
ledOnMs: 50,
color: Colors.purple,
styleInformation: BigTextStyleInformation(""),
ticker: 'ticker');
final NotificationDetails platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
);
await flutterLocalNotificationsPlugin
.show(0, title, body, platformChannelSpecifics, payload: payload);
}
The solution to this problem is below.
There's a problem with platform specifics in the flutter_local_notifications plugin.
For example, if you use
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
.createNotificationChannel(channel);
inside of your local notification initialization function, then the function will stop at this point if you're not on an android device. This results in not initializing the plugin with ios + android settings.
Solution
To fix this just wrap everything you do with .resolvePlatformSpecificImplementation into a platform check
if (Platform.isAndroid) {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
.createNotificationChannel(channel);
}
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}