I would like an app to open a dialog box every day at 2pm, even if the user is doing something else and is not currently in the app interface at this time.
How to do this with Flutter, such that it will work both on Android and iOS?
I was thinking about a method like this:
timer = Timer.periodic(Duration(seconds: 60), (Timer t) => checkTime());
that checks every minute if it's between 14:00:00 and 14:00:59, with a method similar to
flutter run function every x amount of seconds, but this seems like a waste of resource: there is probably better, with a more natural way to wake up an app in the background at a precise timing?
Question: how to make an app display a dialog box at 2pm every day, even if the user is doing something else/is in another app, with Flutter?
Note: if the device has its screen off (i.e. user is not using their phone), the dialog box should be displayed the next time the screen is turned on.
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 !!
TL,DR: Use alarm_manager_service. It can schedule tasks for a particular time, and if needed, have it repeat after set duration from that start time.
You were planning to have the full code in the main app. The problem is, there is no guarantee that the app will not be closed by Android OS. With, power management features (doze), the app will likely be killed in hours. Recent android versions give users explicit control. The user will have to excuse this app from power optimizations(disable battery optimization). Even so, RAM management can kill the app in critical situations. This is expected behaviour.
Now, about displaying an interface to foreground: Android also seems to discourage intrusive app behaviours like bringing an activity to the foreground that obstructs the user while he is interacting with another activity. See https://developer.android.com/guide/components/activities/background-starts. It also lists exceptions, whereby you can achieve this. (I know Facebook/messenger used to do this and all sorts of background activities even after killing tasks without respect for recommendations. But then most of us hate FB apps for being too intrusive, and have given me an unethical impression).
Running the app continuously only to check for a particular time of day is certainly waste of resource.
So you will have to register a background service apart from the main GUI app code. Dart apps run as isolates. You can create a separate isolate for the background service apart from the main GUI that the user interacts with. Now, even if the main GUI isolate is closed, the background service can run.
You'll need to modify android manifest file also when doing these. I can point you to some leads:
Use an alarm_manager_service to schedule background tasks at the set time.This can then callback to carry out activity and show a dialog box or wake the app.
Another one: workmanager
Read this quick and to the point summary given as the readme description to understand the existing scenario in android OS. This actually sums up everything that I read through countless developer.android articles.
SAMPLE CODES:
You can use alarm manager to schedule tasks for a particular time, and also have it repeat after set duration from the start time ~> start at 2pm some day and repeat it periodically every 24 hours.
The codes for using alarm_manager is given here as answer (Solution1).
I had a similar requirement, and it's a very difficult thing to do with the requirement of drawing over other apps.
But I found an acceptable solution using the flutter_local_notifications package. You can schedule a periodic notification, and you can enable "fullScreenIntent". This link should help: https://pub.dev/packages/flutter_local_notifications#full-screen-intent-notifications
It's not perfect, but for perfect you would have to write native code using PlatformChannels:
https://flutter.dev/docs/development/platform-integration/platform-channels
If you aim to automatically open the App for an iOS-device-user. well, that's not possible. I'm not sure if it is possible for Android as well.
You may want to create a notification to push at 14:00 to ask the user if they want to open the dialog.
Here's the documentation link for Notifications in FlutterFire: Notifications
and Documentation for widgets with Flutter (You'll need Xcode for this): Develop an iOS 14 Widget in Flutter with SwiftUI
This question is vague but I am not sure what to Google for exactly.
But in my app I have a section where you create a list of tasks with various attributes, and a lot of these numbers are summed up and displayed in daily totals visually. But these daily totals should reset every 24 hours (based on the hour of the day the user chooses for the cutoff, e.g. 3 am if someone works late).
Right now: my database can hold all the data by day. Then my daily counters will visually display the numbers by pulling the corresponding data from the database looking for the current day. That's the easy part.
The hard part: I can refresh the counter after the time cutoff if the user rotates the screen or restarts the app because then it'll be looking for items in the database with a new day that won't be found, so everything will be 0 as intended. But what if the user is just staring at the screen as the time cutoff rolls by? How do I make the app refresh the counters once the time hits? What if they're not even using the app at all (either it's minimized in the background or not even active).
Do I need to have some kind of always-running loop in the background that checks the current time against the values in the database? If so, isn't this inefficient if it's always needing to pull values from a database based on time? What's the correct practice for something like this?
You can setup a service and schedule that service to run periodically so that it does whatever job you want it to do
maybe this article can help you.
Alarm manager and services will be ideal for you to implement to do something for your requirement.
Services : It will be running all the time irrespective of your life-cycle of activity.
Alarm manager: Inside services use alarm manager to trigger event to update UI at regular interval.
Finally you can use Local braodcast reciever to update your Activity from services.
You can check implemetation in details below :
Android update activity UI from service
I'm writing a reminder app for Android where users can create custom notifications that will appear at a time of the day that they specify. I realize that there is another similar question, but the only answer was to use the AlarmManager, which, according to the documentation, resets when the device is rebooted. I want the user to be able to set a notification to appear at a certain time on a certain date, meaning that it should retain the information through a reboot.
Ultimately though, the app needs to be notified that it needs to do something.
Eventually, I would also like to have the same behavior when the device reaches a certain location, if you have any thoughts on that. :)
Bear with me, I'm a bit of a novice programmer (I'm 17).
Thanks in advance.
The commentors are correct: you will need to use an AlarmManager to create your alarm and you will need a boot receiver to handle resetting your alarm after a reboot.
GeoLocation and GeoFences are pretty easy. I have an example app here: https://github.com/androidfu/GeofenceExample
You're not going to care about the mock location bits in that example unless you wish to test entering and exiting your target location, but the rest of the code should work for what you need.
Also, GeoFences do not persist a reboot either so it'll be good for you to get familiar with your on-boot receiver ;) You'll want to re-add your GeoFence after a reboot too.
I was read almost all article that have same question in Stackoverflow and somewhere else but those made me confuse.
my problem: I want my App toast something in certain time to the user (like alarm clock App that start ring in certain time) as an example, I want my App 2 days and 10 hour latter show a toast. but, during this period every thing maybe happen like application close, phone will restart or Etc... and the App doesn't show any thing.
my question is: How can do something in certain time in android App?
So now what is the solution? can any one help me and give me a sample code plz?
thank you in advanced,
What you want is an AlarmManager
You can also find a tutorial here. If you are scheduling a precise time, you might want to actually be conservative and wake yourself up a little early, then schedule a toast using a Timer for finer grained control.
As far as I understood the official documentation about Widgets I am a little bit confused.
The "standard" way would be to define a BroadcastReceiver and define the update frequency in milliseconds - this way allows a minimum update interval of 30 minutes to save battery power. Sounds reasonable.
The "manual" way I found reading the Google documentation would be to handle the update of widgets yourself using the AlarmManager. Using this method higher update intervals are possible (though of course discouraged!) and it would be possible to use alarm types that do not wake up the device when asleep. (I assume the intent is sent any time after the event should trigger as soon as the device wakes up for some other reason - is that right??)
Now, I get confused by the following thought: widgets reside on home screens. Or at least that's the most common place they will be found. Android offers many pages (standard is 5 or 7) on home screens, so a Widget, even though placed there by the user, might not even be visible!
As long as the information a widget displays is just a very simple text (like the current time!) that could be calculated or derived without any delay whenever needed, I do not want any update frequency or even device wake-up intents when it is not visible!
But as long as the device is on, or more specific: as long as the screen is on AND the widget is visible, I want a lot of update events! Like a clock displaying the seconds needs an intent to redraw every second!
How can that be realized? How is the "Android analog clock" realized? Neither method A ("standard") nor B ("manual") give my high update frequency but only as long as the device is on and my widget is visible.
Can anybody give me a hint???
I assume the intent is sent any time after the event should trigger as soon as the device wakes up for some other reason - is that right??
Yes.
I do not want any update frequency or even device wake-up intents when it is not visible!
But your users do, in many cases. Anything you do that is worth doing in the update may take some number of seconds. The user is not going to sit there waiting some number of seconds. Hence, the app widget update model says that you keep the app widget updated constantly, so when the user goes looking at the app widget, they have the updated data right away.
But as long as the device is on, or more specific: as long as the screen is on AND the widget is visible, I want a lot of update events! Like a clock displaying the seconds needs an intent to redraw every second!
Write your own home screen app.
How is the "Android analog clock" realized?
It is a feature of the home screen app.