I am using Flutter Local Notification to trigger periodic notifications in my app.
It provides a callback, which is executed when user taps on the notification,
I want to use the callback to run a async function, but i don't want to launch the app when the user clicks on it. I simply want to dismiss the notification.
Is there any way to achieve it?
Here is my code.
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_notificationPlugin = FlutterLocalNotificationsPlugin();
_notificationPlugin.initialize(
initializationSettings,
onSelectNotification: onSelectNotification,
);
My callback function,
Future onSelectNotification(String payload) async {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text("Hello"),
content: Text("content"),
),
);
AnAsyncFunction();
}
Notification triggering function,
Future getPeriodicNoification() async {
print("hello");
// // Show a notification every minute with the first appearance happening a minute after invoking the method
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id',
'your channel name',
'your channel description',
importance: Importance.Max,
priority: Priority.High,
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await _notificationPlugin.periodicallyShow(0, 'repeating title',
'repeating body', RepeatInterval.EveryMinute, );
}
Related
I'm working on a Flutter App with Firebase Messaging. The notifications work perfectly fine on iOS. On Android, they work when the app is in the foreground, but are not displayed when the app is in background or terminated. I could already rule out doze mode, as the app has been put to background just seconds before triggering the message. The logfile also says, the message is received by the devices, but somehow not displayed.
The problem also only exists when the app is installed via .apk and not when I build directly with Android Studio, so I thought maybe the fingerprinting could cause the problem. But the messages are received by the device and just not displayed -> so that's not it either, right?
I use firebase_messaging: ^12.0.0 as the plugin.
Here is the implementation of my background handler:
static Future<void> setUp() async {
await Firebase.initializeApp(
name: 'Firebase-App',
options: DefaultFirebaseOptions.currentPlatform,
);
//... iOS stuff
//Enable Foreground-Messages for Android
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.max,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await configLocalNotification(flutterLocalNotificationsPlugin);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
//Display Foreground-Message on Android
flutterLocalNotificationsPlugin.show(
message.hashCode,
Uri.decodeComponent(message.data['title']).replaceAll('+', ' '),
Uri.decodeComponent(message.data['message']).replaceAll('+', ' '),
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: '#mipmap/ic_launcher',
importance: Importance.max,
),
),
payload: json.encode(message.data),
);
});
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
static Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message) async {
await Firebase.initializeApp();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.max,
);
await flutterLocalNotificationsPlugin.show(
message.hashCode,
Uri.decodeComponent(message.data['title']).replaceAll('+', ' '),
Uri.decodeComponent(message.data['message']).replaceAll('+', ' '),
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: '#mipmap/ic_launcher',
importance: Importance.max,
// other properties...
),
),
payload: json.encode(message.data),
);
}
static Future<void> configLocalNotification(
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async {
const initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
const initializationSettingsIOS = IOSInitializationSettings();
const initializationSettings = InitializationSettings(
iOS: initializationSettingsIOS, android: initializationSettingsAndroid);
//Handle on click event when App is in foreground or background
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//handle on click event when app is terminated
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
final String? selectedNotificationPayload =
notificationAppLaunchDetails!.payload;
debugPrint(
'notification payload on launch: $selectedNotificationPayload');
await onSelectNotification(selectedNotificationPayload);
}
}
Thanks in advance for your help, I'm really at the end of the line here!
I am developing water drinking reminder app with flutter.
I want to schedule a list of time specified local notifications that user can add to this list and delete from this list. like this
Any help would appreciate, Thanks.
After hours of research I have solved this problem.
The full code is below.
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
class NotificationHelper {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
/// Initialize notification
initializeNotification() async {
_configureLocalTimeZone();
const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings("ic_launcher");
const InitializationSettings initializationSettings = InitializationSettings(
iOS: initializationSettingsIOS,
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
/// Set right date and time for notifications
tz.TZDateTime _convertTime(int hour, int minutes) {
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime scheduleDate = tz.TZDateTime(
tz.local,
now.year,
now.month,
now.day,
hour,
minutes,
);
if (scheduleDate.isBefore(now)) {
scheduleDate = scheduleDate.add(const Duration(days: 1));
}
return scheduleDate;
}
Future<void> _configureLocalTimeZone() async {
tz.initializeTimeZones();
final String timeZone = await FlutterNativeTimezone.getLocalTimezone();
tz.setLocalLocation(tz.getLocation(timeZone));
}
/// Scheduled Notification
scheduledNotification({
required int hour,
required int minutes,
required int id,
required String sound,
}) async {
await flutterLocalNotificationsPlugin.zonedSchedule(
id,
'It\'s time to drink water!',
'After drinking, touch the cup to confirm',
_convertTime(hour, minutes),
NotificationDetails(
android: AndroidNotificationDetails(
'your channel id $sound',
'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high,
sound: RawResourceAndroidNotificationSound(sound),
),
iOS: IOSNotificationDetails(sound: '$sound.mp3'),
),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time,
payload: 'It could be anything you pass',
);
}
/// Request IOS permissions
void requestIOSPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
cancelAll() async => await flutterLocalNotificationsPlugin.cancelAll();
cancel(id) async => await flutterLocalNotificationsPlugin.cancel(id);
}
add your custom times like this
for (int i = 0; i < _provider.getScheduleRecords.length; i++) {
_notificationHelper.scheduledNotification(
hour: int.parse(_provider.getScheduleRecords[i].time.split(":")[0]),
minutes: int.parse(_provider.getScheduleRecords[i].time.split(":")[1]),
id: _provider.getScheduleRecords[i].id,
sound: 'sound0',
);
}
You can use flutter_local_notifications plugin, it can send scheduled, instant and also repeating notifications
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'scheduled title',
'scheduled body',
tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
const NotificationDetails(
android: AndroidNotificationDetails(
'your channel id', 'your channel name',
channelDescription: 'your channel description')),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
This example will schedule a notification that appears after 5 seconds.
Try Awesome Notifications.
It has many features including seconds precision scheduled notifications.
I am new to flutter.
Alarm functionality is working unless the app is closed.
After closing the app android alarm manager is not working.
I have put all the tags in AndroidManifest.xml.
On call back this _ringAlarm() method has been called.
Future<void> _ringAlarm() async {
NotificationManager n = new NotificationManager();
n.initNotificationManager();
n.showNotificationWithDefaultSound("Keep it,it's YOURS", widget.text.split("_")[1]);
//n.showNotificationWithAlarmSound();
//Working in Simulator but not in Device
//n._showNotificationCustomSound();
//FlutterRingtonePlayer.playAlarm();
FlutterRingtonePlayer.play(
android: AndroidSounds.alarm,
ios: IosSounds.glass,
looping: false, // Android only - API >= 28
volume: 1, // Android only - API >= 28
asAlarm: false, // Android only - all APIs
);
Future.delayed(const Duration(milliseconds: 4000), () {
FlutterRingtonePlayer.stop();
});
print(Const.todoTextList);
}
Here is implementation of notification manager class
class NotificationManager
{
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
AndroidInitializationSettings initializationSettingsAndroid;
IOSInitializationSettings initializationSettingsIOS;
InitializationSettings initializationSettings;
void initNotificationManager()
{
initializationSettingsAndroid = new AndroidInitializationSettings('#mipmap/ic_launcher');
initializationSettingsIOS = new IOSInitializationSettings();
initializationSettings = new InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
void showNotificationWithDefaultSound(String title, String body)
{
var androidPlatformChannelSpecifics = new AndroidNotificationDetails('your channel id', 'your channel name', 'your channel description', importance: Importance.Max, priority: Priority.High);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
flutterLocalNotificationsPlugin.show(0, title, body, platformChannelSpecifics);
}
static const MethodChannel platform = MethodChannel('your channel name');
/* Future<void> showNotificationWithAlarmSound() async {
/// this calls a method over a platform channel implemented within the
/// example app to return the Uri for the default alarm sound and uses
/// as the notification sound
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
final String alarmUri = await platform.invokeMethod('getAlarmUri');
final UriAndroidNotificationSound uriSound =
//UriAndroidNotificationSound(AndroidSounds.alarm.toString());
UriAndroidNotificationSound(alarmUri);
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'uri channel id', 'your channel name', 'your channel description',
sound: uriSound,
styleInformation: const DefaultStyleInformation(true, true));
final NotificationDetails platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics,iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'uri sound title', 'uri sound body', platformChannelSpecifics);
}*/
//For custom notification
Future<void> _showNotificationCustomSound() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'your other channel id',
'your other channel name',
'your other channel description',
sound: RawResourceAndroidNotificationSound('easy_going'),
);
const IOSNotificationDetails iOSPlatformChannelSpecifics =
IOSNotificationDetails(sound: 'easy_going');
//const MacOSNotificationDetails macOSPlatformChannelSpecifics =
//MacOSNotificationDetails(sound: 'slow_spring_board.aiff');
const NotificationDetails platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'custom sound notification title',
'custom sound notification body',
platformChannelSpecifics);
}
}
It is working good if I don't close actual app.Once I close the app notification will not work.I am unable to reproduce this issue in simulator.If I get any suggestion how to reproduce this in simulator that also will be helpful to me.
I am working on a project, I have used Flutter Local Notifications to show periodic notifications,
I'm trying to figure out if there is a way to not to launch the app on notification click, for example, when a user clicks on a notification, it should just disappear from the notification panel.
This is the code I tried so far,
Initialising,
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_notificationPlugin = FlutterLocalNotificationsPlugin();
_notificationPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
Calling,
Future getPeriodicNoification() async {
print("hello");
// Show a notification every minute with the first appearance happening a minute after invoking the method
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id',
'your channel name',
'your channel description',
importance: Importance.Max,
priority: Priority.High,
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await _notificationPlugin.periodicallyShow(0, 'repeating title',
'repeating body', RepeatInterval.EveryMinute, platformChannelSpecifics);
}
Callback function(On notification click)
Future onSelectNotification(String payload) async {
ThisisAnAsyncFunction();
}
Please help.
You can use the close function under BehaviourSubject that you use when adding the payload.
static final onNotifications = BehaviorSubject<String?>();
then call this when selecting the notification.
onSelectNotification() => onNotifications.close();
I need help, there's an error when calling Local Notification.
For the initState :
initState() {
super.initState();
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
var initializationSettingsAndroid =
new AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
FlutterLocalNotificationsPlugin().initialize(initializationSettings, onSelectNotification: onSelectNotification);
}
For the function :
showNotification() async {
var android = new AndroidNotificationDetails('Channel ID', 'Channel Name', 'channelDescription');
var iOS = new IOSNotificationDetails();
var platform = new NotificationDetails(android, iOS);
await flutterLocalNotificationsPlugin.show(
0, 'New Notification', 'Flutter Local Notif', platform,payload: 'test notification');
}
The error is "PlatformException (PlatformException(error, Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference, null))"
I've already tried on the documentation and also youtube, but I always get this error message
I have faced this, and in my case it was an icon problem app_icon
in your initState function replace this
var initializationSettingsAndroid = new AndroidInitializationSettings('app_icon');
with this
var initializationSettingsAndroid = new AndroidInitializationSettings('#mipmap/ic_launcher');
Hope this helps you.
Add your app_icon.png to MY_PROJECT\android\app\src\main\res\drawable\app_icon.png
However, for me the error was in androidInitialization. I was initializing it this way:
var androidInit = AndroidInitializationSettings('app_icon.png');
Here, the .png shouldn't be added. I know this might be silly but if it helps anyone out there facing the same problem then there you go! This is the correct method:
var androidInit = AndroidInitializationSettings('app_icon');
this one works for me you can give a chance
#override
initState() {
super.initState();
to the Android head project
var initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future<void> _showNotification() async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
importance: Importance.Max, priority: Priority.High, ticker: 'ticker');
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'plain title', 'plain body', platformChannelSpecifics,
payload: 'item x');
}
Future<void> onSelectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: ' + payload);
}
}
There is problem in your plugin initialization. I see in your code, you created the instance flutterLocalNotificationsPlugin but used FlutterLocalNotificationsPlugin().initialize() instead. And then you tried to show notification with the created instance which has not been initialized.
I got this error for the same reason - my FlutterLocalNotificationsPlugin was not initialized properly. To check if it is, I tried the below code:
void main() {
runApp(MyApp());
initializeNotification(); //Its Important to place this line after runApp() otherwise FlutterLocalNotificationsPlugin will not be initialize and you will get the error as mentioned in the question.
}
void initializeNotification() async {
try {
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid = AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: didSelectNotification);
} catch(e) {
print(e.toString());
}
}
If it catch any exception, your flutterLocalNotificationsPlugin has not been initialized, and you will get an error.
Also try to wrap initialization code in separate async-await function.
In my case, I added app_icon.png to the android drawables, in this path : MY_PROJECT\android\app\src\main\res\drawable
Take a look at the source code here
https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications/example/android/app/src/main/res/drawable
Copy Paste all drawables to your project, it will work.
And Don't Forget to add these receivers to Manifest
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
for me adding WidgetsFlutterBinding.ensureInitialized(); to main.dart before creating AndroidInitializationSettings helps.
uture _requestPermissions() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
/// Note: permissions aren't requested here just to demonstrate that can be
/// done later
final DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification: (
int id,
String? title,
String? body,
String? payload,
) async {
didReceiveLocalNotificationSubject.add(
ReceivedNotification(
id: id,
title: title,
body: body,
payload: payload,
),
);
});