I'm trying to learn flutter, but I can't manage to do this. I'm doing a schedule about school that prints all your lessons etc. I want that when a lesson is about to start, a notification will be sent 5 minutes before that the lesson (or something) is about to start.The OS I want this to work is an IOS. Furthermore, I watched some videos using package:flutter_local_notifications/flutter_local_notifications.dart but nothing works on my code. If someone could help, I would be very grateful.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void main(){
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Timer _timer;
String _timeRemaining = '';
@override
void initState() {
super.initState();
_startTimer();
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
void _startTimer() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
_timeRemaining = _getTimeRemaining();
});
});
}
String _getTimeRemaining() {
DateTime now = DateTime.now();
DateTime tomorrow = DateTime(now.year, now.month, now.day + 1);
DateTime nextLesson = _getNextLessonTime();
Duration difference = nextLesson.difference(now);
if (difference.isNegative) {
nextLesson = _getNextLessonTime();
difference = nextLesson.difference(now);
}
int seconds = difference.inSeconds % 60;
int minutes = (difference.inMinutes % 60);
int hours = difference.inHours % 24;
String nextLessonName = _getNextLessonName(nextLesson);
String timeRemaining;
if (now.weekday == DateTime.sunday) {
timeRemaining = 'Non si va a scuola oggi.';
}else if(tomorrow.weekday == DateTime.sunday){
timeRemaining = 'Non si va a scuola domani.';
} else if (now.weekday == DateTime.saturday && now.hour >= 12) {
timeRemaining = 'La giornata scolastica è finita.';
}else if (now.hour >= 14){
timeRemaining = 'La giornata scolastica è finita.';
} else if (difference.inHours >= 24) {
timeRemaining = 'Prossima lezione\n $nextLessonName il ${nextLesson.day}/${nextLesson.month}/${nextLesson.year} fra ${difference.inDays} giorni.';
} else if (now.hour >= nextLesson.hour && now.minute >= nextLesson.minute) {
nextLesson = _getNextLessonTime();
difference = nextLesson.difference(now);
seconds = difference.inSeconds % 60;
minutes = (difference.inMinutes % 60);
hours = difference.inHours % 24;
nextLessonName = _getNextLessonName(nextLesson);
timeRemaining = 'Prossima lezione\n $nextLessonName fra ${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}.';
} else {
timeRemaining = 'Prossima lezione\n $nextLessonName fra ${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}.';
}
return timeRemaining;
}
DateTime _getNextLessonTime() {
DateTime now = DateTime.now();
DateTime nextLesson;
if (now.weekday == DateTime.saturday) {
nextLesson = DateTime(now.year, now.month, now.day, 10, 0);
} else {
nextLesson = DateTime(now.year, now.month, now.day, 8, 0);
if (now.hour >= 14) {
nextLesson = nextLesson.add(const Duration(days: 1));
}
}
return nextLesson;
}
String _getNextLessonName(DateTime nextLesson) {
String nextLessonName = '';
if (nextLesson.weekday == DateTime.monday) {
nextLessonName = 'Telecomunicazioni';
} else if (nextLesson.weekday == DateTime.tuesday || nextLesson.weekday == DateTime.wednesday) {
nextLessonName = 'Italiano';
} else if (nextLesson.weekday == DateTime.thursday) {
nextLessonName = 'Sistemi';
} else if (nextLesson.weekday == DateTime.friday) {
nextLessonName = 'Matematica';
} else if (nextLesson.weekday == DateTime.saturday) {
nextLessonName = 'Telecomunicazioni';
}
return nextLessonName;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Orario',
home: Scaffold(
appBar: AppBar(
title: const Text('Orario'),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Text(
_timeRemaining,
style: const TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildDayButton('Lunedi', context),
_buildDayButton('Martedi', context),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildDayButton('Mercoledi', context),
_buildDayButton('Giovedi', context),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildDayButton('Venerdi', context),
_buildDayButton('Sabato', context),
],
),
const SizedBox(height: 20),
const Text(
'Programma fatto da Skerdi Velo',
style: TextStyle(fontSize: 12),
),
],
),
),
),
);
}
Widget _buildDayButton(String day, BuildContext context) {
String schedule = '';
switch (day) {
case 'Lunedi':
schedule = '08:00-09:00 Telecomunicazioni\n09:00-10:00 Matematica\n10:00-12:00 Italiano\n12:00-13:00 Inglese';
break;
case 'Martedi':
schedule = '08:00-09:00 Italiano\n09:00-10:00 Sistemi\n10:00-11:00 Sistemi\n11:00-12:00 Informatica\n12:00-13:00 Informatica\n13:00-14:00 Informatica';
break;
case 'Mercoledi':
schedule = '08:00-09:00 Italiano\n09:00-10:00 Storia\n10:00-11:00 Informatica\n11:00-12:00 Educazione Fisica\n12:00-13:00 Matematica\n13:00-14:00 Inglese';
break;
case 'Giovedi':
schedule = '08:00-09:00 Sistemi\n09:00-10:00 Matematica\n10:00-11:00 Storia\n11:00-12:00 Informatica\n12:00-13:00 Inglese\n13:00-14:00 T.P.I.';
break;
case 'Venerdi':
schedule = '08:00-09:00 Matematica\n09:00-10:00 Sistemi\n10:00-11:00 Informatica\n11:00-12:00 Educazione Fisica';
break;
case 'Sabato':
schedule = '08:00-09:00 Telecomunicazioni\n09:00-10:00 Telecomunicazioni\n10:00-11:00 T.P.I.\n11:00-12:00 T.P.I.';
break;
}
return ElevatedButton(
onPressed: () {
if (schedule.isNotEmpty) {
_showAlertDialog(context, day, schedule);
}
},
style: ElevatedButton.styleFrom(
minimumSize: const Size(150, 50),
),
child: Text(
day,
style: const TextStyle(fontSize: 20),
),
);
}
void _showAlertDialog(BuildContext context, String day, String schedule) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(day),
content: Text(schedule),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
}
}
This is an implementation which will allow you to schedule notifications using Flutter on IOS.
Imports
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:flutter_push_notifications/utils/download_util.dart';
import 'package:rxdart/subjects.dart';
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
Initializing the notification service
class NotificationService {
NotificationService();
final _localNotifications = FlutterLocalNotificationsPlugin();
final BehaviorSubject<String> behaviorSubject = BehaviorSubject();
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
requestSoundPermission: true,
requestBadgePermission: true,
requestAlertPermission: true,
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
final InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await _localNotifications.initialize(initializationSettings,
onSelectNotification: selectNotification);
}
void onDidReceiveLocalNotification(
int id, String? title, String? body, String? payload) {
print('id $id');
}
void selectNotification(String? payload) {
if (payload != null && payload.isNotEmpty) {
behaviorSubject.add(payload);
}
}
}
Future<NotificationDetails> _notificationDetails() async {
final bigPicture = await DownloadUtil.downloadAndSaveFile(
"https://images.unsplash.com/photo-1624948465027-6f9b51067557?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80",
"drinkwater");
IOSNotificationDetails iosNotificationDetails = IOSNotificationDetails(
threadIdentifier: "thread1",
attachments: <IOSNotificationAttachment>[
IOSNotificationAttachment(bigPicture)
]);
final details = await _localNotifications.getNotificationAppLaunchDetails();
if (details != null && details.didNotificationLaunchApp) {
behaviorSubject.add(details.payload!);
}
NotificationDetails platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iosNotificationDetails);
return platformChannelSpecifics;
}
Set a timezone. Depends on your functionality if you even need it.
tz.initializeTimeZones();
tz.setLocalLocation(
tz.getLocation(
await FlutterNativeTimezone.getLocalTimezone(),
),
);
Finally, the method to schedule a notification. You can subtract the current date from a future date with some offset to find the amount of seconds you need to enter.
Future<void> showScheduledLocalNotification({
required int id,
required String title,
required String body,
required String payload,
required int seconds,
}) async {
final platformChannelSpecifics = await _notificationDetails();
await _localNotifications.zonedSchedule(
id,
title,
body,
tz.TZDateTime.now(tz.local).add(Duration(seconds: seconds)),
platformChannelSpecifics,
payload: payload,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true,
);
}
This article gives a thorough guide: https://blog.codemagic.io/flutter-local-notifications/ This answer mostly highlighted what you needed for your implementation.