Flutte local notification at a specific time daily for android - android

android only
I tried NotificationServices Scheduled method with _flutterLocalNotificationsPlugin.periodicallyShow and it doesn't seems to work.
also how to test it in a android emulator (changing the date and time on the device works or not)
notification_service.dart
class NotificationServices {
FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final AndroidInitializationSettings _androidInitializationSettings =
AndroidInitializationSettings('logo1');
void initialiseNotifications() async {
InitializationSettings initializationSettings = InitializationSettings(
android: _androidInitializationSettings,
);
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
void scheduleNotifications(String title, String body) async {
int hour = 19;
var ogValue = hour;
int minute = 05;
var time = Time(hour,minute,20);
AndroidNotificationDetails androidNotificationDetails =
const AndroidNotificationDetails(
'channelId',
'channelName',
importance: Importance.max,
priority: Priority.high,
);
NotificationDetails notificationDetails = NotificationDetails(
android: androidNotificationDetails,
);
await _flutterLocalNotificationsPlugin.periodicallyShow(
0, 'title', 'body', RepeatInterval.daily, notificationDetails);
}
void stopNotifications() async{
_flutterLocalNotificationsPlugin.cancel(0);
}
}
main.dart
NotificationServices notificationServices = NotificationServices();
notificationServices.initialiseNotifications();
notificationServices.scheduleNotifications('Daily Reminder', 'You have a ToDo list to complete');

Related

How can I save firebase push notification device local when app closed in flutter?

I use Hive_flutter and flutter_local_notifications: ^13.0.0. And I don't have any about saving notifications device local idea when app closed. Can you help me? thanks for your insteresting.
int badgesCount = 0;
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
FirebaseMessaging messaging = FirebaseMessaging.instance;
class PushNotificationsService {
Future initialise() async {
iOSPermission();
messaging.getToken().then((token) async {
print('token is $token');
});
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('#drawable/ic_stat_name');
DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveIos);
InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (payload) async {
if (payload != "") {
log(payload.toString());
}
},
);
FirebaseMessaging.onMessage.listen(
(RemoteMessage message) async {
if (message.notification != null) {
badgeCount += 1;
final remoteModel = RemoteMessageModel.fromJson(message.toMap());
await StorageHiveHelper().save(remoteModel);
var data = message.notification;
var title = data?.title.toString();
var body = data?.body.toString();
var image = message.data['image'] ?? '';
var type = message.data['type'] ?? '';
var id = '';
id = message.data['type_id'] ?? '';
if (Platform.isIOS) return;
if (image != null && image != 'null' && image != '') {
return await generateImageNotication(
title ?? "", body ?? "", image, type, id);
}
}
},
);
messaging.getInitialMessage().then((RemoteMessage? message) {
if (message != null) {
log("Initial Message: " + (message.data.toString()));
pushToNavigate(message);
}
});
FirebaseMessaging.onMessageOpenedApp
.listen((RemoteMessage message) => pushToNavigate(message));
FirebaseMessaging.onBackgroundMessage(getBackGroundMessage);
}
pushToNavigate(RemoteMessage? message) async {
var type = await message?.data['type'] ?? '';
log("OnDidReceiveIOS: " + (message?.data.toString() ?? "null ios payload"));
log(type);
if (type == 'products') {
navService.pushNamed("product/detail", args: 631509);
}
}
void iOSPermission() async {
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
void onDidReceiveIos(
int id, String? title, String? body, String? payload) async {
log("OnDidReceiveIOS: " + (payload?.toLowerCase() ?? "null ios payload"));
try {
var iosDetail = const DarwinNotificationDetails(
presentBadge: true,
presentAlert: false,
presentSound: true,
sound: "cash.caf");
var platformChannelSpecifics = NotificationDetails(iOS: iosDetail);
await flutterLocalNotificationsPlugin.show(
id, title, title, platformChannelSpecifics,
payload: jsonEncode(payload ?? {}));
} on Exception catch (e) {
debugPrint(e.toString());
}
}
I tried saving the message to hive here. It working when app is on but it was not working when the app was totally closed
Future<void> getBackGroundMessage(RemoteMessage message) async {
badgeCount += 1;
await FlutterAppBadger.updateBadgeCount(badgeCount);
final remoteModel = RemoteMessageModel.fromJson(message.toMap());
await StorageHiveHelper().save(remoteModel);
}
}
const String _sound = "notification_sound";
void display(
RemoteMessage message,
NotificationDetails notificationDetails,
) async {
try {
await flutterLocalNotificationsPlugin.show(
message.hashCode,
message.notification?.title,
message.notification?.body,
notificationDetails,
payload: jsonEncode(message.data),
);
} on Exception catch (e) {
debugPrint(e.toString());
}
}
Future<void> generateSimpleNotication(
String title, String msg, String type, String id, RemoteMessage pay) async {
try {
if (Platform.isIOS) return;
log("Payload" + (pay.toMap().toString()));
final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'high_importance_channels',
'High Importance Notifications',
playSound: true,
sound: RawResourceAndroidNotificationSound(_sound),
largeIcon: DrawableResourceAndroidBitmap('#drawable/ic_stat_name'),
importance: Importance.max,
priority: Priority.max, );
var iosDetail = const DarwinNotificationDetails(
presentAlert: true, presentSound: true, sound: "cash.caf");
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iosDetail);
await flutterLocalNotificationsPlugin.show(
id, title, msg, platformChannelSpecifics,
payload: jsonEncode(pay.data));
} on Exception catch (e) {
debugPrint(e.toString());
}
}
I don't understand the main problem. You just want to display the notifications when app is closed or in background? Or you really need to save them to the local database? Anyways, try using this class
import 'dart:async';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class PushNotificationService {
static FirebaseMessaging messaging = FirebaseMessaging.instance;
static final FlutterLocalNotificationsPlugin notificationPlugin =
FlutterLocalNotificationsPlugin();
static const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.high,
);
static String? idPush;
static StreamController<RemoteMessage> _messageStream =
StreamController.broadcast();
static Stream<RemoteMessage> get messagesStream => _messageStream.stream;
static Future _backgroundHandler(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here
}
static Future _onMessageHandler(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here, if you want to use flutter_local_notifications, use the display() method.
}
static Future _onMessageOpenApp(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here
}
// iniciar firebase i notificacions locals
static Future initializeApp() async {
//Push notifications
await Firebase.initializeApp();
idPush = await FirebaseMessaging.instance.getToken();
print('idPush: $idPush');
//Handler
FirebaseMessaging.onBackgroundMessage(_backgroundHandler);
FirebaseMessaging.onMessage.listen(_onMessageHandler);
FirebaseMessaging.onMessageOpenedApp.listen(_onMessageOpenApp);
//local notifications initialization
const InitializationSettings initializationSettings =
InitializationSettings(
iOS: DarwinInitializationSettings(),
android: AndroidInitializationSettings("#mipmap/ic_notification"),
);
notificationPlugin.initialize(initializationSettings);
}
// mètode per obrir una notificació local (només amb l'app oberta)
static void display(RemoteMessage message) async {
try {
await notificationPlugin.show(
message.notification!.hashCode,
message.notification!.title,
message.notification!.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
color: Colors.blue,
icon: '#mipmap/ic_notification',
),
iOS: const DarwinNotificationDetails(
presentAlert: true, presentBadge: true, presentSound: true),
),
);
} on Exception catch (e) {
print(e);
}
}
// demanar permisos
Future<void> requestPermission() async {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
} else if (settings.authorizationStatus ==
AuthorizationStatus.provisional) {
print('User granted provisional permission');
} else {
print('User declined or has not accepted permission');
}
}
static closeStreams() {
_messageStream.close();
}
}
This class will show notifications when app is closed or in background. And if you need to display them with the app opened, you can throught the display method. If you want to save them to hive, just implement that part on the Handlers.
Finally initialize the class in your main:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PushNotificationService.initializeApp();
runApp(const MyApp());
}

Flutter android_alarm_manager_plus does not work reliably

I want to schedule daily notifications at a specific daytime with the android_alarm_manager_plus and the local_notifications plugins.
However, the notifications come in very irregulary. The delay of the notifications increases each consecutive day.
For example, the app should send a reminder everyday at 8:00 am. The first day, the notification comes in at around the right time. The next day, it sends it 15 minutes delayed and the following days, no notification gets send at all.
I tested this on a Motorola Moto G9 Play with Android 11 and I have deactivated the energy-saving mode and made sure that battery-optimizations are turned off for this app.
In the following I created a litte (hopefully) reproducable example:
// initializing similar to the official example
Future<FlutterLocalNotificationsPlugin> _initNotificationsPlugin() async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('flutter_logo');
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings();
final MacOSInitializationSettings initializationSettingsMacOS =
MacOSInitializationSettings();
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
return flutterLocalNotificationsPlugin;
}
Future<void> scheduleNotifications() async {
int id = 0;
AndroidAlarmManager.periodic(Duration(days: 1), id, sendNotification,
exact: true,
allowWhileIdle: true,
rescheduleOnReboot: true,
wakeup: true);
log("Notifications scheduled");
}
// Top-level callback for the AndroidAlarmManager
Future<void> sendNotification() async {
FlutterLocalNotificationsPlugin flutterNotificationsPlugin =
await _initNotificationsPlugin();
await flutterNotificationsPlugin.cancelAll();
final now = DateTime.now();
int id =
now.second + now.minute * 60 + now.hour * 60 * 60; // Daytime in seconds
// Copied from the example with edited channel id, etc.
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'my very own channel id', 'my very own channel name',
channelDescription: 'my channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
//
final body = "Notification sent at ${now.hour}:${now.minute}:${now.second}";
await flutterNotificationsPlugin.show(
id, "Test notification", body, platformChannelSpecifics);
log(body);
}
Future<void> cancelAllAlarmsAndNotifications() async {
await AndroidAlarmManager.cancel(0);
}
And when the user clicks a button, the following code is executed:
onPressed: () {
cancelAllAlarmsAndNotifications().then((value) {
scheduleNotifications();
});
},
Also, the main method:
void main() {
WidgetsFlutterBinding.ensureInitialized();
AndroidAlarmManager.initialize().then((value) {
runApp(const MyApp());
});
}
I really hope that you see some mistake I make that is easy fixable :)
Thanks in advance!

How to schedule multiple time specific local notifications in flutter

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.

Why Flutter Android Alarm Manager is not working in device once the App is closed?

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.

AndroidAlarmManager calls flutterLocalNotificationsPlugin.show(), but no notification is displayed

I have a terrible problem with AlarmManager and FlutterLocalNotification.
When I call show() from AlarmManager callback, in order to write a scheduled notification, no notification is displayed.
I initialise the flutter_local_notification plugin in the main() function of the App in this way:
NotificationManager n = new NotificationManager();
void main() async
{
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
n.initNotificationManager();
runApp(MainClass());
}
NotificationManager class is:
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, String payload)
{
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, payload: payload);
}
}
In the initState() of a page inside the App I make AlarmManager calls the callback in this way:
void initState()
{
super.initState();
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), 0, alarmCallback);
//......
}
The callback is:
alarmCallback()
{
n.showNotificationWithDefaultSound("Title", "MySuperBody", "Hey, this is the Payload!");
return;
}
How can I fix this?
The solution is to migrate your project to AndroidX using Refractor in android studio.

Categories

Resources