The problem is in detail
I use the Awesome_notifications package. The notifications work in a good way from time to time, but no sometimes they only work when the application is opened. The Awesome_notifications package says that this is due to the power saving mode of the devices.
See the picture:[1]: https://i.sstatic.net/4ajWVQ9L.jpg
Note: I schedule notifications according to the time specified by the user
2:How to use
background_fetch
with
Awesome_notifications
// code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:device_preview/device_preview.dart';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:showcaseview/showcaseview.dart';
import 'package:upgrader/upgrader.dart';
import 'package:background_fetch/background_fetch.dart';
// [Android-only] This "Headless Task" is run when the Android app is terminated with `enableHeadless: true`
// Be sure to annotate your callback function to avoid issues in release mode on Flutter >= 3.3.0
@pragma('vm:entry-point')
void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
// This task has exceeded its allowed running-time.
// You must stop what you're doing and immediately .finish(taskId)
print("[BackgroundFetch] Headless task timed-out: $taskId");
BackgroundFetch.finish(taskId);
return;
}
print('[BackgroundFetch] Headless event received.');
// Do your work here...
//Notification
notfi();
BackgroundFetch.finish(taskId);
}
TimeOfDay _timeOfDay = const TimeOfDay(hour:5, minute: 0);
void main()async{
WidgetsFlutterBinding.ensureInitialized();
await Permission.notification.isDenied.then(
(value) {
if (value) {
Permission.notification.request();
}
}
);
AwesomeNotifications().initialize(
null,
[
NotificationChannel(
channelKey: 'basic_keyadh',
channelName: 'chnneladhs',
channelDescription: 'fghjks',
importance: NotificationImportance.Max,
//channelShowBadge:true,
defaultRingtoneType: DefaultRingtoneType.Notification,
onlyAlertOnce: true,
),
],
channelGroups: [
NotificationChannelGroup(
channelGroupName: 'Basic group',
channelGroupKey: 'basic_channel_group'
),
],
debug: true,
);
// await NotificationService.initializeNotifications();
runApp(DevicePreview(enabled: true,builder: (context) => const MyApp23 (),
),
);
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
}
class MyApp23 extends StatefulWidget {
const MyApp23({super.key});
@override
State<MyApp23> createState() => _MyApp23State();
}
class _MyApp23State extends State<MyApp23> with WidgetsBindingObserver {
// Be sure to annotate your callback function to avoid issues in release mode on Flutter >= 3.3.0
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
// Configure BackgroundFetch.
int status = await BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.NONE
), (String taskId) async { // <-- Event handler
// This is the fetch-event callback.
print("[BackgroundFetch] Event received $taskId");
setState(() {
});
// IMPORTANT: You must signal completion of your task or the OS can punish your app
// for taking too long in the background.
BackgroundFetch.finish(taskId);
}, (String taskId) async { // <-- Task timeout handler.
// This task has exceeded its allowed running-time. You must stop what you're doing and immediately .finish(taskId)
print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
BackgroundFetch.finish(taskId);
});
print('[BackgroundFetch] configure success: $status');
setState(() {
});
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
}
@override
void dispose(){
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
//Set the fit size (Find your UI design, look at the dimensions of the device screen and fill it in,unit in dp)
return ScreenUtilInit(
//designSize: const Size(360, 690),
minTextAdapt: true,
splitScreenMode: true,
// Use builder only if you need to use library outside ScreenUtilInit context
builder: (_ , child) {
return ShowCaseWidget(
builder : (context) => MaterialApp(
debugShowCheckedModeBanner: false,
//title: 'First Method',
// You can use the library anywhere in the app even in theme
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp),
),
home: UpgradeAlert(
dialogStyle: UpgradeDialogStyle.cupertino,
upgrader: Upgrader(
// minAppVersion:"1.0.0",
debugLogging:true,
debugDisplayAlways:true,
languageCode:'ar',
messages: UpgraderMessages(
code: 'ar',
),
// durationUntilAlertAgain: const Duration(days: 1),
),
child: child),
),
);
},
child: const Demo(),
);
}
}
///Stings
class Demo extends StatefulWidget{
const Demo({super.key});
@override
State<Demo> createState() => _DemoState();
}
class _DemoState extends State<Demo> with SingleTickerProviderStateMixin {
@override
void initState() {
super.initState();
getSavedData();
}
getSavedData() async {
final pref = await SharedPreferences.getInstance();
//appData.MyColor = Color(pref.getInt('MyColor')??Colors.white.value);
//appData.col1= pref.getBool('col1') ??appData.col1;
//appData.col2= pref.getBool('col2') ??appData.col2;
// get the saved value from stored prefs
// and make sure to do it inside `setState`
// cannot use DateTime.parse because _timeOfDaybgm.toString() doesn't return a value
// DateTime.parse can understand
setState(() {
int ssavedHour = pref.getInt('_timeOfDay') ?? _timeOfDay.hour;
int ssavedMinute = pref.getInt('_timeOfDay2') ??_timeOfDay.minute;
_timeOfDay = TimeOfDay(hour: ssavedHour, minute: ssavedMinute);
//////////////////////////////////////////////////////////////////////////////////
});
}
@override
void dispose(){
super.dispose();
}
@override
Widget build(BuildContext context) {
// notfi();
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
centerTitle:true,
backgroundColor:const Color.fromARGB(255, 241, 204, 100),
scrolledUnderElevation: 0.0,
title:const Text(
"Demo",
style: TextStyle(
color:Colors.white,
fontWeight: FontWeight.bold,
)
,),
) ,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
//mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(onPressed: () async {
final TimeOfDay?timeOfDay = await showTimePicker(
context: context,
initialEntryMode: TimePickerEntryMode.dialOnly,
initialTime:_timeOfDay,
builder: (BuildContext context, Widget? child){
return Theme(
data: Theme.of(context).copyWith(
textTheme: const TextTheme(
// ignore: deprecated_member_use
button: TextStyle(
//fontSize: BoodyTextSize(),
),
// ignore: deprecated_member_use
subtitle1: TextStyle(
),
// ignore: deprecated_member_use
bodyText2: TextStyle(
//fontSize: Titlesize(),
color:Color.fromARGB(255, 239, 158, 52),
),
),
colorScheme: const ColorScheme.light(
onBackground:Color.fromARGB(255, 253, 199, 126),
tertiaryContainer: Color.fromARGB(255, 253, 199, 126),
primary:Color.fromARGB(255, 253, 199, 126),
)),
child: child!,
) ;
}
);
if (timeOfDay!= null) {
setState(() {
_timeOfDay=timeOfDay;
});
// ignore: use_build_context_synchronously
FocusScope.of(context).unfocus();
final prefs = await SharedPreferences.getInstance();
// changed setString to setInt, just makes it easier
await prefs.setInt('_timeOfDay', _timeOfDay.hour);
await prefs.setInt('_timeOfDay2', _timeOfDay.minute);
}
}, child: const Text("Schedule",style: TextStyle(color: Colors.red),)),
)
],
) ,
);
}
}
//Notification
notfi() {
AwesomeNotifications().createNotification(
schedule:NotificationCalendar(
// allowWhileIdle:true,
// preciseAlarm: true,
hour: _timeOfDay.hour,
minute: _timeOfDay.minute,
second: 0,
repeats: true,
),
/* actionButtons: <NotificationActionButton>[
NotificationActionButton(
key: 'accept',
label: 'قراه',
color: const Color.fromARGB(183, 79, 34, 240),
),
NotificationActionButton(
key: 'reject',
label: 'اغلاق ',
color: const Color.fromARGB(183, 79, 34, 240),
),
],*/
content: NotificationContent(
// icon: 'resource://mipmap/shado',
id:2,
channelKey: 'basic_keyadh',
title: 'He works',
// body: '',
),
);
}
I want to use the background_fetch package, but the problem is that I don’t know the method and where to put the code to fetch notifications. Is it inside the background call function?!
Thanks to everyone who helped me.
2
Answers
Notifications do not come at all when adding this code.
And in main.dart initialize:
Create Notify:
You are making this implementation complex for yourself, Use: Awesome_notification, Awesome_notification_fcm
And in main.dart initialize:
Create Notify: