Anonymous
Как сохранить уведомление об обратном отсчете флаттера, даже если приложение удалено из последних приложений?
Сообщение
Anonymous » 25 май 2024, 19:05
Я пытался запустить обратный отсчет на панели уведомлений в приложении. Но каждый раз, когда я удаляю приложение из последних приложений, таймер в последний раз останавливается, прежде чем полностью закрыть приложение.
Я попробовал несколько вещей, которые вы можете увидеть ниже
Код: Выделить всё
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(),
);
}
}
Код: Выделить всё
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,
),
),
),
);
}
}
я говорю о showSilentCountdownNotification в этом файле.
Код: Выделить всё
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]
1716653116
Anonymous
Я пытался запустить обратный отсчет на панели уведомлений в приложении. Но каждый раз, когда я удаляю приложение из последних приложений, таймер в последний раз останавливается, прежде чем полностью закрыть приложение. Я попробовал несколько вещей, которые вы можете увидеть ниже [code]main.dart[/code] [code]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(), ); } } [/code] [code]countdown_page.dart[/code] [code]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, ), ), ), ); } } [/code] [code]notification_service.dart[/code] я говорю о showSilentCountdownNotification в этом файле. [code]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]