I want the notification to display on particular time which end-user selects it using time picker. i'm confused with the process of how to do that. please guide me to solve this problem.
Getting variable from model:
late var selectedTime = TimeOfDay.now();
User picks the time from front-end:
Future<Null> selectTime (BuildContext context) async{
picked = (await showTimePicker(
context: context,
initialTime: model.selectedTime,
))!;
if (picked != null){
setState(() {
model.selectedTime = picked;
this.preferences?.setString("dateValue", model.selectedTime.format(context));
});
}
}
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
child: GestureDetector(
onTap: (){
selectTime(context);
},
child: Text(
'${this.preferences?.getString("dateValue") ?? model.defaultTime.format(context)}',
),
),
This class contains notifications sepearately.
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final mymodel = myModel();
Future<void> firstNotifications() async{
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
const AndroidNotificationDetails firstNotificationSpecifics =
AndroidNotificationDetails(
'channel id',
'channel name',
'channel description',
sound: RawResourceAndroidNotificationSound('song1'),
playSound: true,
enableVibration: false ,
visibility: NotificationVisibility.secret,
autoCancel: true,
timeoutAfter:7000
);
const NotificationDetails firstNotificationPlatformSpecifics =
NotificationDetails(android: firstNotificationSpecifics);
await flutterLocalNotificationsPlugin.zonedSchedule
(1, null, null, tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)), firstNotificationPlatformSpecifics,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true);
}
But now this code play notification after 5 seconds which i had given manually. but i want the notification to display at the user picked time.
You need to call the setNotification function after you picked the time
Future<Null> selectTime (BuildContext context) async{
picked = (await showTimePicker(
context: context,
initialTime: model.selectedTime,
))!;
if (picked != null){
setState(() {
model.selectedTime = picked;
setNotification(picked);//Call it here
this.preferences?.setString("dateValue", model.selectedTime.format(context));
});
}
}
void setNotification( TimeOfDay selectedTime) {
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// final mymodel = myModel();
Future<void> firstNotifications() async {
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
const AndroidNotificationDetails firstNotificationSpecifics =
AndroidNotificationDetails(
'channel id', 'channel name', 'channel description',
sound: RawResourceAndroidNotificationSound('song1'),
playSound: true,
enableVibration: false,
visibility: NotificationVisibility.secret,
autoCancel: true,
timeoutAfter: 7000);
const NotificationDetails firstNotificationPlatformSpecifics =
NotificationDetails(android: firstNotificationSpecifics);
tz.TZDateTime zonedTime = tz.TZDateTime.local(DateTime.now().year,DateTime.now().month,DateTime.now().day,selectedTime.hour,
selectedTime.minute).subtract(DateTime.now().timeZoneOffset);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
null,
null,
tz.TZDateTime.now(tz.local) ,
firstNotificationPlatformSpecifics,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true);
}
}
Related
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 have built my own application in flutter and I have implemented Local notifications and also FirebaseMessaging:
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
firebaseMessaging.requestNotificationPermissions();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid
? showNotification(message['notification'])
: showNotification(message['aps']['alert']);
return ;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
firebaseMessaging.getToken().then((token) {
print('token: $token');
FirebaseFirestore.instance
.collection('Consultant')
.doc(firebaseUser.uid)
.update({'deviceToken': token});
}).catchError((err) {
//Fluttertoast.showToast(msg: err.message.toString());
});
}
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => NotificationsScreen(payload: payload,)),
);
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'it.wytex.vibeland_pro_app'
: 'it.wytex.vibeland_pro_app',
'Vibeland',
'Vibeland',
playSound: true,
enableVibration: true,
importance: Importance.max,
priority: Priority.high,
ongoing: true,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
print(message);
print(message['body'].toString());
print(json.encode(message));
await flutterLocalNotificationsPlugin.show(0, message['title'].toString(),
message['body'].toString(), platformChannelSpecifics,
payload: json.encode(message));
await flutterLocalNotificationsPlugin.show(
0, '📩 Hai ricevuto un messaggio 📩 ', 'Controlla subito le Tue notifiche 🔔🔔', platformChannelSpecifics,
payload: 'item x',
);
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('vibeland_pro');
var initializationSettingsIOS = new IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
I wrote a function into index.js to push also firestore notification when user creates order etc..
Everything works fine, I got Localnotifications when all is open and FCM notifications when app is in background, the problem is when the app sleep...
after some minutes the app goes in sleep mode and to start it again you need to restart the application which keep my user Logged:
MultiProvider(
providers: [
Provider<AuthenticationProvider>(
create: (_) => AuthenticationProvider(FirebaseAuth.instance),
),
StreamProvider(
create: (context) => context.read<AuthenticationProvider>().authState,
)
],
child: MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(
),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
}
)
),
debugShowCheckedModeBanner: false,
title: 'Vibeland Admin Authentication',
home: Authenticate(),
),
);
}
}
class Authenticate extends StatelessWidget {
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return StartScreenLogged();
}
return StartScreen();
}
}
but if I dont run again the app I dont get the notification because the app sleep.
what we need to do in this case?
Im using a solution with FCM and Local notifications to receive specific push notifications on a channel. Everything works for Android.
I send my push notifications trough Postman to https://fcm.googleapis.com/fcm/send and that all works pretty well.
However when I add my iPhone, and finished all the installation steps that were needed. The only thing I receive is the print in my console on flutter with the message. I don't receive any kind of notification on the iPhone itself.
final FirebaseMessaging _fcm = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid;
var initializationSettingsIOS;
var initializationSettings;
void _showNotification() async {
//await _buildNotification();
}
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
// Or do other work.
}
Future<void> _createNotificationChannel(
String id, String name, String description) async {
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var androidNotificationChannel = AndroidNotificationChannel(
id,
name,
description,
importance: Importance.Max,
playSound: true,
sound: RawResourceAndroidNotificationSound('not_kiddin'),
enableVibration: true,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(androidNotificationChannel);
}
Future<void> _buildNotification(String title, String body) async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'my_channel',
'Channel Name',
'Channel Description.',
importance: Importance.Max,
priority: Priority.High,
playSound: true,
enableVibration: true,
sound: RawResourceAndroidNotificationSound('not_kiddin'),
ticker: 'noorderlicht');
var iOSChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, title, body, platformChannelSpecifics,
payload: 'payload');
}
#override
void initState() {
super.initState();
initializationSettingsAndroid =
AndroidInitializationSettings('ic_launcher');
initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_fcm.requestNotificationPermissions();
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
print(message);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//_showNotification();
Map.from(message).map((key, value) {
print(key);
print(value);
print(value['title']);
_buildNotification(value['title'], value['body']);
});
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
}
Future onDidReceiveLocalNotification(
int id, String title, String body, String payload) async {
// display a dialog with the notification details, tap ok to go to another page
showDialog(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: Text(title),
content: Text(body),
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: Text('Ok'),
onPressed: () {},
)
],
),
);
}
Future onSelectNotification(String payload) async {
if (payload != null) {
debugPrint('Notification payload: $payload');
}
}
_fcm.requestNotificationPermissions();
You need to request for permission in iOS (android dont need).
_fcm.requestNotificationPermissions(
const IosNotificationSettings(
sound: true, badge: true, alert: true, provisional: true));
FCM messages come in different structures for IOS, in your case remove the 'data' when the platform is IOS like these below.
if(Platform.isAndroid){
roomId = message['data']['chatRoomId'];
senderId = message['data']['senderId'];
}else if(Platform.isIOS){
roomId = message['chatRoomId'];
senderId = message['senderId'];
}
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, );
}
In the application I use rabbitmq, background_fetch and flutter_local_notifications.
When the application is launched or minimized everything works fine, but when it is closed I cannot run my application in background, i can not find any information about this, all another questions only for FCM, no more info about flutter with amqp, I am a newbee in this framework
main.dart
Future<void> backgroundFetchHeadlessTask(String taskId) async {
await Rabbitmq.getDelivery();
BackgroundFetch.finish(taskId);
}
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
// Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function
final BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject = BehaviorSubject<ReceivedNotification>();
final BehaviorSubject<String> selectNotificationSubject = BehaviorSubject<String>();
NotificationAppLaunchDetails notificationAppLaunchDetails;
void main() async {
runApp(MyApp());
await initPlatformState();
}
Future<void> initPlatformState() async {
BackgroundFetch.configure(BackgroundFetchConfig(
startOnBoot: true,
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.ANY
), (String taskId) async {
await backgroundFetchHeadlessTask(taskId);
}
);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
_requestIOSPermissions();
_configureDidReceiveLocalNotificationSubject();
_configureSelectNotificationSubject();
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
}
void _requestIOSPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
void _configureDidReceiveLocalNotificationSubject() {
didReceiveLocalNotificationSubject.stream
.listen((ReceivedNotification receivedNotification) async {
await showDialog(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: receivedNotification.title != null
? Text(receivedNotification.title)
: null,
content: receivedNotification.body != null
? Text(receivedNotification.body)
: null,
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: Text('Ok'),
onPressed: () async {
Navigator.of(context, rootNavigator: true).pop();
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(selectedPage: 3),
//SecondScreen(receivedNotification.payload),
),
);
},
)
],
),
);
});
}
void _configureSelectNotificationSubject() {
selectNotificationSubject.stream.listen((String payload) async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => LandingPage(selectedPage: 3)),//SecondScreen(payload)),
);
});
}
#override
void dispose() {
didReceiveLocalNotificationSubject.close();
selectNotificationSubject.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'My first app',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: LandingPage(),
);
}
}
And inside rabbitmq.dart
class Rabbitmq {
static Future getDelivery() async
{
var auth = await DBProvider.db.getAuth();
print(hash);
Client client = new Client(
settings: ConnectionSettings(
host: 'myhost',
authProvider: AmqPlainAuthenticator('user', 'password')
)
);
client
.channel()
.then((Channel channel) => channel.queue("queue", durable: true))
.then((Queue queue) => queue.consume())
.then((Consumer consumer) => consumer.listen((AmqpMessage message) async {
Map messageBody = message.payloadAsJson;
if(messageBody.containsKey('message') == true && messageBody.containsKey('from') == true)
{
await Rabbitmq()._showNotification(messageBody['message'], messageBody['from']);
}
})
);
}
Future<void> _showNotification(String text, String from) async {
var initializationSettingsAndroid = new AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
FlutterLocalNotificationsPlugin().initialize(initializationSettings);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'com.example.g2r_market/chat', 'Уведомления чата', 'Настройка уведомлений для чатов',
importance: Importance.Max, priority: Priority.High, ticker: 'ticker'
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, from, text, platformChannelSpecifics,
payload: 'item x');
}
}