Persistent stopwatch that can be paused/unpaused in flutter - flutter

My flutter app allows users to time how long they have been working for. I'm using the package stop_watch_timer.
Everything works fine except when the app gets killed in the background, because then I lose the timer value and it goes back to 0. As users are likely to start the timer then put their phone away and work for a while, the app getting killed is a very likely scenario and I need to make sure that this never happens. Another feature that I need in the app is for users to be able to pause and unpause the timer whenever they want.
Here are the solutions I have come up with so far and their problems:
Solution 1: Store the start DateTime on the phone using shared_preferences and calculate the current timer value when app is reopened by simply calculating the duration between start time and DateTime.now(). But then I realised that this does not work if the user had paused and unpaused the timer at some point.
Solution 2: Store the current timer value as a RestorableInt. This works if the timer is on pause when the app gets killed, but does not work if the timer is meant to be running when the app dies.
Any suggestions or ideas??

You should store something like this:
[
{"start":1664027960},
{"pause":1664027975},
{"unpause":1664027979},
{"pause":1664028061},
{"unpause":1664028065},
]
Everytime a user hits the pause button you add the time to the list and store it in the shared_prefs or in a json file. Same for unpausing.
You can then calculate the total ellapsed time.

Related

Flutter - Timer pauses unintentionally

I have implemented a Timer as detailed in the article below, so that the timer will keep running when i change tabs.
How to implement persistent stopwatch in Flutter?
I have an issue where the Timer "loses" or pauses time, only when not plugged into my computer. When i plug it into my computer, no issues, the emulator runs fine too. I test the flutter timer against a timer on my computer or phone, and after 5mins, they match. But when my phone (Galaxy S9) isn't plugged in, after 5mins of real time, the flutter timer might only be up to 2mins, when i go back into the app the timer is running but the timer wont be what it should be. It doesn't crash or reset, its counting when i get back into the app. I'm finding it hard to debug as when I plug the phone into my computer it seems to work fine! Any ideas?
I had issues with this as well. Things working correctly when running on the Simulator is fools gold. The Timer won't run in the background like you want it to unless you do specific work to keep it running. Here is the official page from Flutter on doing work in the background: https://flutter.dev/docs/development/packages-and-plugins/background-processes
I'll suggest implementing didChangeAppLifecycleState method of the WidgetsBindingObserver and detect when the app goes to the background and when it's back in the foreground. At the point where the app goes into the background, you save the current time e.g (onPauseTime) (you can use SharedPreferences here) and the Duration left on the timer (timerDurationLeft).
When the app is back in the foreground you check if the timer was running before the app entered the background state, if it was, you then check the current time e.g (onResumeTime) and calculate the time difference in seconds (onResumeTime - onPauseTime), using the time difference and the timerDurationLeft you can calculate how much time the timer has left to run and you start/resume the timer from that point or end/set the timer to 0:00 if time has already passed.
P:S Using a background service would be the way to go if you intend to perform some actions in the middle, like set notifications at some point where the timer is almost complete.

Iphone sdk - How to play a sound during a phone call after some elapsed time?

Well I am having two issues that i can't get to work, related to audio and calls.
The first one is to play a sound during a phone call. I don't want to play continuous music or stream anything, it is just a simple and short sound that the user will hear at one time during his call.
I have read some posts claiming that this is possible, and I even have an application that does so, but I can't get it to work. My app identifies the call using CTCallCenter and print the logs but never plays the sound or plays it after the app comes to foreground again. I have the .plist property of required background mode App plays audio.
The second issue, is to play the sound after some elapsed time. NSTimers doesn't work when on background mode, nor NSThread sleep on my background process or NSOperation. So how could I play this sound after say 10 seconds of the call?
Also, this behavior has to work also when the application is already on background mode. With CTCallCenter I am only getting the event when the application is interrupted from use, but I don't see any logs when i send the app to background and then begin/receive a call
.
If anyone could point me to the right direction I'll be really grateful.
I havent done this, but NSLocalNotifcation, schedule a notification to play when you app get the call to move into the background. I would expect this to work. Interested to find out if it does.

Is a Timer disabled automatically when app resigns active on the iphone?

Playing around with Timers, and trying to make them behave right when app is sent to background, killed etc.
Judging by the generated comments in xcode, you should disable/invalidate timers on resignActive/enterBackground events.
However, i havent done that yet, but checked what happens to my timer when i click the home button and then re-enter the app.
I basically have a method in my view that the timer triggers every second:
NSLog(#"workedTimTimerTick workedTime; %#", timeString);
And when i exit the app, the output stops, when i re-enter the app, the output starts again...
Since i'm not doing anything code-wise to the timer on those lifecycle events, how come it stops getting called?
Input appreciated!
Your app is suspended when it enters background mode (Application States and Transitions).
Your timer won't fire when the app is in background and the time spent in background isn't taken into account for the timer delay.

Multitasking: Stop Background Audio at Specific Time

I am developing an iphone app which uses background audio (on an infinite loop) to continue playing after the app has entered the background.
My problem is I want to implement a "sleep timer" which stops playback after a specified period of time.
Is this possible? I have spent an hour looking for a method to do this with no avail.
EDIT: My current thought is to use a lower level API, the Audio Queue Services, and manually re-fill the queue with another instance of the loop during the AudioQueueOutputCallback. If the timer has expired I do not fill the loop. I'm assuming this should work since the documentation says audio callbacks are still fired when an app is playing multitasking background audio. Can anyone think of a better way or a reason why this wouldn't work?
While you queue sound data on the background your app remains fully functional and running as if it was in the foreground (well almost), so yes, you should just write a timer that stops the playback at a given time and it will be fired as expected.
Now to the second question: once you stop queueing things up, your app will be "frozen" until the user manually brings it to the foreground... So what you should do is start queueing audio data from the second file before the first one is done playing, and if you DO need to pause or stop, maybe a solution is to play 0 bytes (silence)?
I'm not actually sure this would be allowed in the App Store. An app is not allowed to execute at all in the background, with the exception of VoIP apps and push notifications.

applicationWillTerminate and background: terribly confused

I understand that applicationWillTerminate is no longer called in iOS4, practically. But I have this situation:
my audiobook goes in background mode and keeps playing audio;
until version 3.x of SDK I saved the point where one listened to the MP3 file, in applicationWillTerminate;
now I was told to keep this saving in applicationWillTerminate (for iPhone 3G) and to implement the same method in applicationDidEnterBackground: but this saves NOT the point where user was at the end, just the point when he entered the background...
But, which is the moment, or better the invoked method, where user exits the application from the application dock? Does this exist?
ApplicationWillTerminate is called when there is a memory problem, but really I can't figure what happens when the user himself shuts down the app.
I repeat: applicationDidEnterBackground does not help me because when the user enters in background mode, he can stays in this position for a long time listening to the audiobook and when he starts again the app, after this is shut down, I mean, he will find the position of the audio file when he entered the background mode…
I'm really confused…
Thanks for your help!
You should save the play location automatically in applicationWillResignActive:, applicationDidEnterBackground: regardless of whether the audio keeps playing or not. Then put another save in applicationWillTerminate. That way the last play location is saved regardless of what happens next. The next event simply overwrites the saved play location to update it.
An even better option would be to have the audio player object itself trigger the save whenever it is interrupted e.g [AVAudioPlayerDelegate audioPlayerBeginInterruption:] or similar. It might takes some extra work but it would guarantee that the play location was always saved regardless of the cause of the interruption.