Executing Function Every Second Day in Flutter (Timed) - flutter

I have this simple send mail function in Flutter, and I would like it to be executed (sent) for example every 48 hours. How would I go around doing that? Is there a simple way to time when it is executed? I don't think code is necessary here, but let me know if you need my send mail function (it is regular Mailer function).

You could use the Timer class:
const everySecondDay = const Duration(hours: 48);
final timer = Timer.periodic(everySecondDay, (Timer t) => sendMailFunction());
Then cancel it when appropriate:
timer.cancel();

Related

How to call a function every 5 minutes in flutter?

I'm looking to call a function at 10am, 10.05am, 10.10am, 10.15am....
I tried using
Timer.periodic(Duration(minutes: 5), (Timer t) { function...})
But it doesn't call the function at 10am, 10.05am... If I were to start the timer at 10.02am, it will call the function at 10.07am, 10.12am. Any idea how to workaround this? Thanks in advance!
I found a workaround where i use a timer to trigger a periodic timer
Rough code as shown below:
Timer(nextFiveMinInterval.difference(DateTime.now()),
() { Timer.periodic(Duration(minutes: 5), (Timer t) { function...})
})

How to set a time-specific event in Flutter?

I am trying to get a switch widget to turn off at a specific time of the day.
I have read a lot of the documentations like these
https://stackoverflow.com/questions/15848214/does-dart-have-a-scheduler
https://pub.dev/packages/cron
https://pub.dev/packages/scheduled_timer
All of these which can only allow me to set duration instead of a specific time.
Thus, my only approach right now is by setting up the timer when the switch is turned on.
e.g. 8hrs then it turns off.
Problem: If the user turned on the switch late, the time that it turns off will also be delayed.
So is there an actual way to set an event at a specific time + works even after we onstop/terminate the application?
You can try to do something like this:
I'll simplify the specific time into :
...
var setTime = DateTime.utc(2022, 7, 11, 8, 48, 0).toLocal();
StreamSubscription? subscription;
...
Then you can assign a periodic stream listener:
...
// periodic to run every second (you can change to minutes/hours/others too)
var stream = Stream.periodic(const Duration(seconds: 1), (count) {
//return true if the time now is after set time
return DateTime.now().isAfter(setTime);
});
//stream subscription
subscription = stream.listen((result) {
// if true, insert function and cancel listen subscription
if(result){
print('turn off');
subscription!.cancel();
}
// else if not yet, run this function
else {
print(result);
}
});
...
However, running a Dart code in a background process is more difficult, here are some references you can try:
https://medium.com/flutter/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124
https://pub.dev/packages/flutter_background_service
I hope it helps, feel free to comment if it doesn't work, I'll try my best to help.
After some time I figured it out.
Format
cron.schedule(Schedule.parse('00 00 * * *'), () async {
print("This code runs at 12am everyday")
});
More Examples
cron.schedule(Schedule.parse('15 * * * *'), () async {
print("This code runs every 15 minutes")
});
To customize a scheduler for your project, read this

Fire something inside a listener only if n seconds have passed since receiving last event

I am listening to an event, however, I don't want to print the event every time. There is an event being sent every second but I don't want my print to work every second. How can I make the print inside this listener to fire only, if 10 seconds is past since last event?
For e.g I receive an event, I use the print. I want to store the event somewhere, if 10 seconds is passed since last event, accept another event -> print and so on.
_controller.onLocationChanged.listen((event) {
print(event);
});
You may try something related to an asynchronous method as such. The following code will set the _isListening variable to true after 10 seconds, which will enable the listener to do it's action once again.
class YourClass{
bool _isListening = true;
void yourMethod() {
_controller.onLocationChanged.listen((event) {
if(_isListening){
_isListening = false;
print(event);
Future.delayed(const Duration(seconds: 10)).then((_) => _isListening=true);
}
});
}
}
Edit: Thanks to #pskink, the proper way to do it would be by using the debounceTime method. So in proper way:
_controller.onLocationChanged
.debounceTime(Duration(seconds: 10))
.listen((event) {
print(event);
});
Use the Timer like below:
Timer(const Duration(seconds: 10), (){
print("...");
});

Is it okay to write code logic (if, for, while) inside your build method

I have some data that I need to show in the UI based on the date of the running time
so I'm doing something like this inside my build method after getting my data from the Consumer Widget
DateTime dateTomorrow =
DateTime.now().add(const Duration(days: 1));
String tomorrowDay =
constants.dayFormat.format(dateTomorrow);
isWhileTrue = true;
while (isWhileTrue) {
if (myMainProgram.isDayShown(tomorrowDay)) {
isWhileTrue = false;
} else {
dateTomorrow =
dateTomorrow.add(const Duration(days: 1));
tomorrowDay =
constants.dayFormat.format(dateTomorrow);
}
}
I felt that there is something wrong with my way of handling data and writing some code logic inside my build method but I couldn't think of any other way to do it.
So is it wrong to write things like this inside your main function? and if not what are my other options?
No Its not okay to do like this because when ever the build function would rebuild by setState the data will revert.
The best way is to calculate in initState funtion.
InitState is the first function that is called when the widget is build and it runs once.
void initState(){
super.initState();
..your logic
}

Ensure processing of a REST call in flutter app in background

I need to ensure that a certain HTTP request was send successfully. Therefore, I'm wondering if a simple way exists to move such a request into a background service task.
The background of my question is the following:
We're developing a survey application using flutter. Unfortunately, the app is intended to be used in an environment where no mobile internet connection can be guaranteed. Therefore, I’m not able to simply post the result of the survey one time but I have to retry it if it fails due to network problems. My current code looks like the following. The problem with my current solution is that it only works while the app is active all the time. If the user minimizes or closes the app, the data I want to upload is lost.
Therefore, I’m looking for a solution to wrap the upload process in a background service task so that it will be processed even when the user closes the app. I found several posts and plugins (namely https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124 and https://pub.dartlang.org/packages/background_fetch) but they don’t help in my particular use case. The first describes a way how the app could be notified when a certain event (namely the geofence occurred) and the second only works every 15 minutes and focuses a different scenario as well.
Does somebody knows a simple way how I can ensure that a request was processed even when there is a bad internet connection (or even none at the moment) while allowing the users to minimize or even close the app?
Future _processUploadQueue() async {
int retryCounter = 0;
Future.doWhile(() {
if(retryCounter == 10){
print('Abborted after 10 tries');
return false;
}
if (_request.uploaded) {
print('Upload ready');
return false;
}
if(! _request.uploaded) {
_networkService.sendRequest(request: _request.entry)
.then((id){
print(id);
setState(() {
_request.uploaded = true;
});
}).catchError((e) {
retryCounter++;
print(e);
});
}
// e ^ retryCounter, min 0 Sec, max 10 minutes
int waitTime = min(max(0, exp(retryCounter)).round(), 600);
print('Waiting $waitTime seconds till next try');
return new Future.delayed(new Duration(seconds: waitTime), () {
print('waited $waitTime seconds');
return true;
});
})
.then(print)
.catchError(print);
}
You can use the plugin shared_preferences to save each HTTP response to the device until the upload completes successfully. Like this:
requests: [
{
id: 8eh1gc,
request: "..."
},
...
],
Then whenever the app is launched, check if any requests are in the list, retry them, and delete them if they complete. You could also use the background_fetch to do this every 15 minutes.