Я попробовал несколько вещей, которые вы можете увидеть ниже
Код: Выделить всё
main.dartКод: Выделить всё
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:ly/screens/countdown_page.dart';
import 'package:ly/services/notification_service.dart';
import 'package:timezone/data/latest.dart' as tz;
void main() {
tz.initializeTimeZones();
WidgetsFlutterBinding.ensureInitialized();
final NotificationService notificationService = NotificationService();
notificationService.flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('app_icon'),
),
onDidReceiveNotificationResponse: (NotificationResponse response) async {
if (response.payload != null && response.payload == 'cake_button') {
// Navigate to a specific screen
// Add your navigation logic here
}
},
);
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Lawfully Yours',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const CountdownPage(),
);
}
}
Код: Выделить всё
countdown_page.dartКод: Выделить всё
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:ly/services/notification_service.dart';
import 'package:ly/utils/colors.dart';
class CountdownPage extends StatefulWidget {
const CountdownPage({super.key});
@override
State createState() => _CountdownPageState();
}
class _CountdownPageState extends State {
late Timer _countdownTimer;
String remainingHours = '00';
String remainingMinutes = '00';
String remainingSeconds = '00';
final NotificationService _notificationService = NotificationService();
@override
void initState() {
super.initState();
// Start the countdown timer
_startCountdown();
// Schedule the birthday notification
_notificationService.scheduleBirthdayNotification(DateTime(2024, 6, 15, 0, 0, 0));
// Show the silent countdown notification
_notificationService.showSilentCountdownNotification(DateTime(2024, 6, 15, 0, 0, 0));
}
@override
void dispose() {
_countdownTimer.cancel();
super.dispose();
}
void _startCountdown() {
final now = DateTime.now();
final userBirthday = DateTime(2024, 6, 15, 0, 0, 0); // June 15, 2024, 12:00 AM
// Calculate remaining time until user's birthday
final difference = userBirthday.difference(now);
setState(() {
final totalHours = difference.inHours;
remainingHours = '$totalHours';
remainingMinutes = '${difference.inMinutes.remainder(60)}';
remainingSeconds = '${difference.inSeconds.remainder(60)}';
});
// Update countdown every second
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
final now = DateTime.now();
final difference = userBirthday.difference(now);
if (difference.isNegative) {
_countdownTimer.cancel();
_notificationService.showBirthdayNotification();
} else {
setState(() {
final totalHours = difference.inHours;
remainingHours = '$totalHours';
remainingMinutes = '${difference.inMinutes.remainder(60)}';
remainingSeconds = '${difference.inSeconds.remainder(60)}';
});
}
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/cd_bg.png'),
fit: BoxFit.cover,
),
),
child: Column(
children: [
Expanded(
flex: 4,
child: Container(),
),
Expanded(
flex: 3,
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColors.primary,
Color(0xFF865368),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(33.0),
topRight: Radius.circular(33.0),
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
width: 40,
height: 10,
decoration: const BoxDecoration(
color: AppColors.accent,
borderRadius:
BorderRadius.all(Radius.circular(100))),
),
),
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: Text(
'COUNTDOWN',
style: TextStyle(
color: AppColors.text,
fontFamily:
GoogleFonts.dmSerifDisplay().fontFamily,
fontSize: 40,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 45.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildCountdownBox(remainingHours),
_buildCountdownBox(remainingMinutes),
_buildCountdownBox(remainingSeconds),
],
),
)
],
),
),
),
),
],
),
),
),
);
}
Widget _buildCountdownBox(String value) {
return Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
color: AppColors.text,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: Center(
child: Text(
value.padLeft(2, '0'),
style: TextStyle(
fontFamily: GoogleFonts.dmSerifDisplay().fontFamily,
fontSize: 40,
),
),
),
);
}
}
Код: Выделить всё
notification_service.dartКод: Выделить всё
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter/material.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
class NotificationService {
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
NotificationService() {
_initializeNotifications();
}
void _initializeNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/launcher_icon');
const InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
);
tz.initializeTimeZones();
}
Future showBirthdayNotification() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'birthday_channel',
'Birthday Notifications',
channelDescription: 'Channel for birthday notifications',
importance: Importance.max,
priority: Priority.high,
color: Color(0xFF6A1B9A),
playSound: true,
styleInformation: BigTextStyleInformation(
'Let’s cut your cake and celebrate this special day together!',
contentTitle: 'Happy Birthday, My Love!',
summaryText: 'Tap to celebrate!',
htmlFormatContent: true,
htmlFormatContentTitle: true,
htmlFormatSummaryText: true,
),
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'Happy Birthday, My Love!',
'Let’s cut your cake and celebrate this special day together!',
platformChannelSpecifics,
payload: 'birthday_notification',
);
}
Future scheduleBirthdayNotification(DateTime scheduledDate) async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'birthday_channel',
'Birthday Notifications',
channelDescription: 'Channel for birthday notifications',
importance: Importance.max,
priority: Priority.high,
color: Color(0xFF6A1B9A),
playSound: true,
styleInformation: BigTextStyleInformation(
'Let’s cut your cake and celebrate this special day together!',
contentTitle: 'Happy Birthday, My Love!',
summaryText: 'Tap to celebrate!',
htmlFormatContent: true,
htmlFormatContentTitle: true,
htmlFormatSummaryText: true,
),
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
'Happy Birthday, My Love!',
'Let’s cut your cake and celebrate this special day together!',
tz.TZDateTime.from(scheduledDate, tz.local),
platformChannelSpecifics,
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.wallClockTime,
matchDateTimeComponents: DateTimeComponents.time,
);
}
Future showSilentCountdownNotification(DateTime userBirthday) async {
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'countdown_channel',
'Countdown Notifications',
channelDescription: 'Channel for countdown notifications',
importance: Importance.low,
priority: Priority.low,
playSound: false,
vibrationPattern: Int64List(0),
ongoing: true,
onlyAlertOnce: true,
styleInformation: BigTextStyleInformation(
'Time remaining: ${_formatDuration(userBirthday.difference(DateTime.now()).inSeconds)}',
contentTitle: 'Birthday Countdown',
summaryText: 'Time remaining: ${_formatDuration(userBirthday.difference(DateTime.now()).inSeconds)}',
htmlFormatContent: true,
htmlFormatContentTitle: true,
htmlFormatSummaryText: true,
),
);
final NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
2,
'Birthday Countdown',
'Time remaining: ${_formatDuration(userBirthday.difference(DateTime.now()).inSeconds)}',
platformChannelSpecifics,
);
// Update countdown every second
Timer.periodic(const Duration(seconds: 1), (timer) {
final seconds = userBirthday.difference(DateTime.now()).inSeconds;
if (seconds
Подробнее здесь: [url]https://stackoverflow.com/questions/78532988/how-to-keep-my-flutter-countdown-notification-running-even-when-app-is-removed-f[/url]