how to add notification permission in flutter local notification - flutter

I'm simply adding a local notification, however in real device notification is appears but without making a sound. For certain real devices, the notification is enabled by default, but we have to manually enable it in some devices. can anyone know how should i add permission in this code
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;
class NotificationService {
final FlutterLocalNotificationsPlugin notificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> initNotification() async {
AndroidInitializationSettings initializationSettingsAndroid =
const AndroidInitializationSettings('mipmap/ic_launcher');
var initializationSettingsIOS = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
onDidReceiveLocalNotification:
(int id, String? title, String? body, String? payload) async {});
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
await notificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse:
(NotificationResponse notificationResponse) async {});
}
notificationDetails() {
return const NotificationDetails(
android: AndroidNotificationDetails('channelId', 'channelName',
importance: Importance.max,
playSound: true,
),
iOS: DarwinNotificationDetails());
}
Future showNotification(
{int id = 0, String? title, String? body, String? payLoad}) async {
return notificationsPlugin.show(
id, title, body, await notificationDetails());
}
Future scheduleNotification(
{int id = 0,
String? title,
String? body,
String? payLoad,
required DateTime scheduledNotificationDateTime}) async {
return notificationsPlugin.zonedSchedule(
id,
title,
body,
tz.TZDateTime.from(
scheduledNotificationDateTime,
tz.local,
),
await notificationDetails(),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}
}

You can use permission_handler plugin to request permission on iOS, android and windows.
For Example:
PermissionStatus status = await Permission.notification.request();
if (status.isGranted) {
// notification permission is granted
}
else {
// Open settings to enable notification permission
}
if you are using for iOS then don't forget to add this in you pod file
post_install do |installer|
installer.pods_project.targets.each do |target|
... # Here are some configurations automatically generated by flutter
# Start of the permission_handler configuration
target.build_configurations.each do |config|
# You can enable the permissions needed here. For example to enable camera
# permission, just remove the `#` character in front so it looks like this:
#
# ## dart: PermissionGroup.camera
# 'PERMISSION_CAMERA=1'
#
# Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.notification
'PERMISSION_NOTIFICATIONS=1',
]
end
# End of the permission_handler configuration
end
end

Related

Flutter local notifications daily scheduled notification

I've been trying to get Flutter local notifications to work since a week but can't get it to work.
Basically the issue is whenever i create a daily notification, it works only for the first time and then it doesn't show notifications every next day.
Suppose if i set daily scheduled notification at 12:20 PM, it will show notification at 12:20 PM for first time, then the next day it won't show. And when i see the list of pending notifications i can see the notification still present.
here's all my notification code
class NotificationService {
// Singleton pattern
static final NotificationService _notificationService =
NotificationService._internal();
factory NotificationService() {
return _notificationService;
}
NotificationService._internal();
static const channelId = "1";
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
static const AndroidNotificationDetails _androidNotificationDetails =
AndroidNotificationDetails(
channelId,
"thecodexhub",
channelDescription:
"This channel is responsible for all the local notifications",
playSound: true,
priority: Priority.high,
importance: Importance.high,
);
static const IOSNotificationDetails _iOSNotificationDetails =
IOSNotificationDetails();
final NotificationDetails notificationDetails = const NotificationDetails(
android: _androidNotificationDetails,
iOS: _iOSNotificationDetails,
);
Future<void> init() async {
const AndroidInitializationSettings androidInitializationSettings =
AndroidInitializationSettings('#mipmap/ic_launcher');
const IOSInitializationSettings iOSInitializationSettings =
IOSInitializationSettings(
defaultPresentAlert: false,
defaultPresentBadge: false,
defaultPresentSound: false,
);
const InitializationSettings initializationSettings =
InitializationSettings(
android: androidInitializationSettings,
iOS: iOSInitializationSettings,
);
// *** Initialize timezone here ***
tz.initializeTimeZones();
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: onSelectNotification,
);
}
Future<void> requestIOSPermissions() async {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
Future<void> showNotification(
int id, String title, String body, String payload) async {
await flutterLocalNotificationsPlugin.show(
id,
title,
body,
notificationDetails,
payload: payload,
);
}
Future<void> scheduleNotification(int id, String title, String body,
DateTime eventDate, TimeOfDay eventTime, String payload,
[DateTimeComponents? dateTimeComponents]) async {
final scheduledTime = eventDate.add(Duration(
hours: eventTime.hour,
minutes: eventTime.minute,
));
await flutterLocalNotificationsPlugin.zonedSchedule(
id,
title,
body,
tz.TZDateTime.from(scheduledTime, tz.local),
notificationDetails,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true,
payload: payload,
matchDateTimeComponents: dateTimeComponents,
);
}
Future<void> cancelNotification(int id) async {
await flutterLocalNotificationsPlugin.cancel(id);
}
Future<void> cancelAllNotifications() async {
await flutterLocalNotificationsPlugin.cancelAll();
}
Future getNotifications() async {
final List<PendingNotificationRequest> pendingNotificationRequests =
await FlutterLocalNotificationsPlugin().pendingNotificationRequests();
return pendingNotificationRequests;
}
}
Future<void> onSelectNotification(String? payload) async {
// await navigatorKey.currentState
// ?.push(MaterialPageRoute(builder: (_) => DetailsPage(payload: payload)));
}
and here's how i'm calling it.
await notificationService.scheduleNotification(
1,
_textEditingController.text,
"Reminder for your scheduled event at ${eventTime!.format(context)}",
eventDate!,
eventTime!,
jsonEncode({
"title": _textEditingController.text,
"eventDate": DateFormat("EEEE, d MMM y").format(eventDate!),
"eventTime": eventTime!.format(context),
}),
getDateTimeComponents(),
);
}
here is getDateTimeComponents if it matters
DateTimeComponents? getDateTimeComponents() {
if (segmentedControlGroupValue == 1) {
return DateTimeComponents.time;
} else if (segmentedControlGroupValue == 2) {
return DateTimeComponents.dayOfWeekAndTime;
}
}
it's been week since i'm trying to fix this issue.
Thank you for reading.
Here it says
Use zonedSchedule instead by passing a date in the future with the
same time and pass DateTimeComponents.matchTime as the value of the
matchDateTimeComponents parameter.
You seem to use DateTimeComponents.time correctly but I guess your date is not in the future. Can you try adding like a thousand years to your date and see? Maybe because after the first firing, the date is now in the past and it will not fire on the next day because of it.

How to add Scheduled notification in flutter

I have been trying to add a scheduled notification feature to my todo app but am unable to do so, when the notification is supposed to appear, it does not and the app crashes, I want the notification to be added when the add button in the todoScreen is clicked.
any help would be really appreciated.
todoScreen link: https://github.com/Rohith-JN/Reminders_App/blob/main/lib/Screens/TodoScreen.dart
notification link: https://github.com/Rohith-JN/Reminders_App/blob/main/lib/notification_service.dart
Okay pushing notification with flutter is pretty easy.
Add these dependencies to pubspec.yaml:
dependencies:
flutter_local_notifications: ^1.4.2
rxdart: ^0.23.1
Particular plugins: flutter_local_notifications and rxdart
then run this command in the terminal:
flutter pub get
Go to AndroidManifest.xml in /android/app/src/main/ and add these lines:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Now, go to AppDelegate.swift in /ios/Runner/ Add:
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as ?
UNUserNotificationCenterDelegate
}
before these lines:
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
Done?
Now, Create a notifications_helper.dart file and import the flutter_local_notifications and rxdart packages.
Then in that file add these:
class NotificationClass{
final int id;
final String title;
final String body;
final String payload;
NotificationClass({this.id, this.body, this.payload, this.title});
}
Also add these finals:
final rxSub.BehaviorSubject<NotificationClass> didReceiveLocalNotificationSubject =
rxSub.BehaviorSubject<NotificationClass>();
final rxSub.BehaviorSubject<String> selectNotificationSubject =
rxSub.BehaviorSubject<String>();
Now finally add the following method to helper file:
Future<void> initNotifications(
notifs.FlutterLocalNotificationsPlugin
notifsPlugin) async {
var initializationSettingsAndroid =
notifs.AndroidInitializationSettings('icon');
var initializationSettingsIOS = notifs.IOSInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification:
(int id, String title, String body, String payload) async {
didReceiveLocalNotificationSubject
.add(NotificationClass(id: id, title: title, body: body, payload: payload));
});
var initializationSettings = notifs.InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
await notifsPlugin.initialize(initializationSettings,
onSelectNotification: (String payload) async {
if (payload != null) {
print('notification payload: ' + payload);
}
selectNotificationSubject.add(payload);
});
print("Notifications initialised successfully");
}
For permission request method for iOS:
void requestIOSPermissions(
notifs.FlutterLocalNotificationsPlugin notifsPlugin) {
notifsPlugin.resolvePlatformSpecificImplementation<notifs.IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
Done Up To This?
Now, scheduled notification, add these:
Future<void> scheduleNotification(
{notifs.FlutterLocalNotificationsPlugin notifsPlugin,
String id,
String title,
String body,
DateTime scheduledTime}) async {
var androidSpecifics = notifs.AndroidNotificationDetails(
id, // This specifies the ID of the Notification
'Scheduled notification', // This specifies the name of the notification channel
'A scheduled notification', //This specifies the description of the channel
icon: 'icon',
);
var iOSSpecifics = notifs.IOSNotificationDetails();
var platformChannelSpecifics = notifs.NotificationDetails(
androidSpecifics, iOSSpecifics);
await notifsPlugin.schedule(0, title, "Scheduled notification",
scheduledTime, platformChannelSpecifics); // This literally schedules the notification
}
Now modify the main.dart file:
NotificationAppLaunchDetails notifLaunch;
final FlutterLocalNotificationsPlugin notifsPlugin=
FlutterLocalNotificationsPlugin();
Now within the main method, add
notifLaunch = await notifsPlugin.getNotificationAppLaunchDetails();
await initNotifications(notifsPlugin);
requestIOSPermissions(notifsPlugin);
NOW MAIN THING,
Triggering a scheduled Notification, Import your helper file and main.dart:
import '../helpers/notifications_helper.dart';
import '../main.dart';
Now call the scheduleNotification method:
scheduleNotification(
notifsPlugin: notifsPlugin, //Or whatever you've named it in main.dart
id: DateTime.now().toString(),
body: "A scheduled Notification",
scheduledTime: DateTime.now()); //Or whenever you actually want to trigger it
And My friend you are done!👍

How to display multiple notifications using flutter plugin : flutter_local_notifications

Here is my code below :
const AndroidNotificationChannel notificationChannel = AndroidNotificationChannel(
'high_importance_channel',
'high importance Notificaion',
'this channel is used for import notification',
importance: Importance.high,
playSound: true,
);
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
Future<void> firebaseBackgroundMessageHandler(RemoteMessage message) async {
await firebaseMessageHandler(message);
}
Future<void> firebaseForegroundMessageHandler(RemoteMessage message) async {
await firebaseMessageHandler(message);
}
Future<void> firebaseMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
try {
flutterLocalNotificationsPlugin.show(
message.notification.hashCode,
message.data["title"].toString(),
message.data["body"].toString(),
NotificationDetails(
android: AndroidNotificationDetails(notificationChannel.id, notificationChannel.name, notificationChannel.description),
));
} catch (_err) {}
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(firebaseBackgroundMessageHandler);
FirebaseMessaging.onMessage.listen(firebaseForegroundMessageHandler);
//FirebaseMessaging.onMessageOpenedApp.listen(firebaseMessageHandler);
final AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('e_app');
final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(notificationChannel);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(alert: true, badge: true, sound: true);
}
The code is working fine for a single notification but whenever I send multiple notifications to android, it shows only the last notification in the status bar.
Could anyone help me about
how to show multiple notifications in the status bar using the flutter local notification plugin?
If you want to group your notifications, there is an option to do that in flutter_local_notifications.
To do this, you can add the following in your code
for ios : threadIdentifier in IOSNotificationDetails
for android : groupChannelId, groupChannelName, groupChannelDescription,
You can find these in the docs here: https://pub.dev/packages/flutter_local_notifications#displaying-a-notification under 'Grouping notifications'.
Basically notifications under same threadId or groupId will all be grouped and shown

Flutter show Snacksbar after time on different screen

Inside my app the user can download some data. If that finished I would like to show a Snackbar.
I know I can show it inside a Widget with:
ScaffoldMessenger.of(context).showSnackBar(snackBar);
The thing is that the user can change Screen during the download. But the user should still be prompted with the snackbar no matter the page he is currently on.
What is the best way to achieve this? I couldn't find anything on this... Let me know if you need more info!
Not sure if this is what you are looking for but using the package below might be the simplest way to achieve it.
flutter_local_notifications: ^5.0.0+1 // I used this version to test the concept.
Edit the LocalNotificationService configuration to your need, like to silently notify the user.
Setup the package from flutter_local_notification.
// Setting up flutter_local_notifications: ^5.0.0+1 as a Service
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class LocalNotificationService {
static final instance = LocalNotificationService();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
initialize() async {
tz.initializeTimeZones();
var initializationSettingsAndroid =
AndroidInitializationSettings('ic_notification');
var initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification,
);
var initializationSettings = InitializationSettings(
iOS: initializationSettingsIOS,
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: (String payload) {
// Do something on notification click
return null;
}
);
}
Future<void> scheduleNotification({
int id,
String body,
String title,
String payload,
DateTime scheduledNotificationDateTime,
}) async {
final epoch = scheduledNotificationDateTime.microsecondsSinceEpoch;
var androidSpecifics = AndroidNotificationDetails(
'$epoch',
title,
body,
priority: Priority.low,
importance: Importance.min,
);
var iOSSpecifics = IOSNotificationDetails();
NotificationDetails platformChannelSpecifics = NotificationDetails(
iOS: iOSSpecifics,
android: androidSpecifics,
);
final tzTime = tz.TZDateTime.fromMicrosecondsSinceEpoch(tz.local, epoch);
await flutterLocalNotificationsPlugin.zonedSchedule(
id,
title,
body,
tzTime,
platformChannelSpecifics,
payload: payload,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.wallClockTime,
);
}
Future onDidReceiveLocalNotification(
int i, String string1, String string2, String string3) async {}
Future cancelAllNotifications() async {
await flutterLocalNotificationsPlugin.cancelAll();
}
Future cancelNotification({int withId}) async {
await flutterLocalNotificationsPlugin.cancel(withId);
}
}
Call this function from anywhere,
LocalNotificationService.instance.scheduleNotification(
body: "This is test notification",
title: "Testing",
id: 1222,
scheduledNotificationDateTime: DateTime.now(),
);
You use the downloading function on the new dart file and put the snack bar on that page after the download succeeded you can call it. that's working now properly or use the mounting method to call the snack bar function.
Use the flush bar package to give the best output.

how to open a certain page using local notification in Flutter? (Not FCM)

no, I am not asking about Firebase Cloud Messaging notification here, but purely using local notification package from here flutter local notification
I want if my user click the notification then it will be directed to a certain page. how to do that ?
currently my code is like this
class LocalNotificationService {
late FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin;
LocalNotificationService._privateConstructor() {
_init();
}
static final LocalNotificationService _instance = LocalNotificationService._privateConstructor();
static LocalNotificationService get instance => _instance; // singleton access
void _init() {
_flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
_initializePlatformSpecifics();
}
Future<void> _initializePlatformSpecifics() async {
var androidInitializationSettings = AndroidInitializationSettings("app_notification_icon");
var iOSInitializationSettings = IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
onDidReceiveLocalNotification: (id, title, body, payload) async {
// do something if notification is clicked
},
);
final initializationSettings = InitializationSettings(
android: androidInitializationSettings,
iOS: iOSInitializationSettings,
);
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
void showSimpleNotification({
required String title,
required String body,
required NotificationType notificationType,
}) async {
var android = _setAndroidNotificationDetails(notificationType);
var ios = IOSNotificationDetails();
var notificationDetails = new NotificationDetails(android: android, iOS: ios);
await _flutterLocalNotificationsPlugin.show(
1, // only need to show one notification in the notification tray, so it is ok if we use the Notification ID
title,
body,
notificationDetails,
);
}
}
First thing you need to create a GlobalKey for navigation like the following:
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
and inside MaterialApp, set the navigatorKey property to be our created key like the following property
navigatorKey: navigatorKey
Now you can use the navigation methods from inside the current state of key, example:
navigatorKey.currentState!.push()
i recommend reading plugin documentation
as per documentation
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
onDidReceiveLocalNotification: onDidReceiveLocalNotification,
);
final MacOSInitializationSettings initializationSettingsMacOS =
MacOSInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false);
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
you can pass onSelectNotification function which will be called whenever user click on notification
from this function u can redirection to particular screen example as below
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) =>
SecondScreen(payload)),);
}