My solution would be using the workmanager
(Current version 0.4.1) flutter package to achieve the requirement you are looking for. Since it is maintained by Flutter Community team , we can expect a long term support.
Based on their documentation
Flutter WorkManager is a wrapper around Android's WorkManager and iOS' performFetchWithCompletionHandler, effectively enabling headless
execution of Dart code in the background.
This is especially useful to run periodic tasks, such as fetching remote data on a regular basis.
Android work manager will automatically handles the background processes by itself based on the OS level of version it is running.
And coming to iOS, based on their doc the feature that this package use to perform background operation is deprecated. But Flutter community team is ready to push the replacement in the upcoming release as per their comment in the GitHub repo. So upgrading to the latest version will help you to solve this issue.
Initialize the wrokmanager
inside the main()
Workmanager().initialize(
callbackDispatcher, // The top level function, aka callbackDispatcher
isInDebugMode:
true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
);
and then schedule the task like below
Workmanager().registerOneOffTask("1", "simpleTask_1",
initialDelay: Duration(seconds: 15));
Workmanager().registerPeriodicTask("102", "simplePeriodicTask_1",
initialDelay: Duration(seconds: 15),
frequency: Duration(minutes: 15)); // Set your 2 PM frequency here.
Refer documentation and setup for available options on scheduling tasks.
And define a callbackDispatcher
and it needs to be either a static function or a top level function to be accessible as a Flutter entry point as per the documentation.
//Defined outside main()
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print(
"Native called background task: callbackDispatcher"); //simpleTask will be emitted here.
createNotify(); // Created a local notification to make sure everything works in background - In your case show alert here.
return Future.value(true);
});
}
// your main() goes here
Instead of displaying notification, derive your logic down to show the alert popup.
EDIT 1 :
To answer your questions in comments
How do you check the program only runs once per day at around 14:00:00
PM?
Scheduled work is stored in an internally managed SQLite database and WorkManager takes care of ensuring that this work persists and is rescheduled across device reboots. And this will be executed multiple times until it is cancelled manually.
Apart from this for dev purpose you can set minimum interval and verify like 1 hour once. And minimum supported interval for work manager is 15 minutes. Even if you set below that threshold time, 15 minutes is set as default.
It seems that your code does a periodic run but it doesn't run at a
specific time.
This is not supported out of the box till now. But we can make use of initial delay while scheduling the task. Calculate the time difference between present time and time you want to trigger.
For example , if I want to schedule some task at 9'o clock and when the scheduling the task you can do the following
When app is opened at 7'o clock , then set the initial delay as two hours.
Refer the stackoverflow answer related to this.
Also, with this method, are you sure it won't be automatically closed
by the OS for battery saving?
According to WorkManager doc, the execution will happen during the period interval that we specify. Since WorkManager is subject to OS battery optimizations, such as doze mode we need to note that execution may be delayed but not cancelled.
Last thing: can a background process start a popup without user
interaction? (other answers mention it's not really possible). Thanks
again!
For me this is the tricky part. Technically, we cannot able to show UI without user actions from the background. Because, UI needs context
based on which is shown to user. So coming to dart
point, it may be hard to show some alert popup that you are seeking for. But if you just want to show only some sort of information, you can give it a try to FlutterToast
as it will be shown to the user from background.
EDIT 2
The requirement that you are seeking to display alert during, when app is not open is called as Draw over other apps and it works only in Android as far as I guess since there is no such feature in iOS.
You can refer this package in flutter for showing alert as per your requirements. Combine the WorkManager
with this package implementation to achieve your desired result. I have not tried with this package but let me know if you face any issues.
Happy Coding !!