Android: How to make multiple CountdownTimers work on background? - android

I have an App where the user can create multiple countdown alarms. Each one has it's own name, time to count, ringtone, etc.
I extended the CountDownTimer to hold each alarm setup and created a Singleton manager to manage all the alarms.
Everything is working fine until I leave the App.
The counters don't actually die. They have a weird behavior. After starting a counter:
1) if I press back key until the home screen and then power off the screen the alarm will trigger as it should.
2) if I press the home button then turn off the screen it will trigger only if I open the app.
3) if I just turn off the screen while still on the app it will trigger as soon as I turn on the screen.
I expected trouble because for that kind of thing I need to use Services, Handlers or other stuff like these.
The problem is, I'm new to Android and after reading a lot about it, I couldn't find a solution.
As far as I understood I should use Services, but it can have only one instance. How would I work with multiple alarms?
Is there other way of doing it?
I need a way to start each alarm and tell the system to keep counting no matter what happens! (and to call an Activity when it finishes)
Any help?

Is there other way of doing it?
If your goal is to alert the user of events in the future, regardless of whether your app is running, dump all your CountdownTimer logic, and switch to AlarmManager. It is specifically designed for this sort of scenario. You can set up an AlarmManager event for each timer, to get control when the end time is reached.
Also note that you will need to maintain information about your registered events in a file or database:
so users can add and remove them, and
so you can set up AlarmManager again if the user reboots their device
and to call an Activity when it finishes
Users may reject your app for that behavior. Not everyone wants to be interrupted in the middle of what they are doing with their device. Please allow this to be configurable, so the user can opt for something less intrusive, like a Notification.

You should replace your CountdownTimers with AlarmManager (as in CommonsWare's answer), after setting it up it will trigger your function to execute on specified time, here is official guide:
http://developer.android.com/training/scheduling/alarms.html
Soon you will find that after device reboot your alarms are lost, you need to restart them by catching android.intent.action.BOOT_COMPLETED broadcast.
Also you should not do a lot of work in your alarm onReceive, you should pass information to some other component like IntentService, to make it safe while device is asleep you should use WakeLock (sample project).
[edit] ---- you should also store your alarm/ringtone related data in some persistant storage, you can use for it shared preferences, or (more work) sqlite database.

I you really want to use timer (i.e. when you want to show countdowns on screen):
You don't have to have multiple timers to show multiple countdowns.
Everything you have to do is just put the target time into some collection, or event put it into the View.setTag().
Then you have timer (let say 1s tick) - on every single tick you have to iterate over all your gauges, check the target time and current time, parse the number and adjust the gauge.
However - as the timers works on separate (non main) threads - you will have to use handler or something like that.
If you want to just set some alarms - take the CommonsWare's answer - it's good one.

Related

Background task timers on iOS

I have an android/winphone application. Small part of app (background broadcastreceiver/task) from time to time (approx 10-15 minutes) checks local file with timestamps and if difference between one of timestamps and current time becomes more than - say - 30 minutes, it shows a notification to a user.
In Android I use AlarmManager.setRepeating(...) to setup periodic check, and to run this setup code I register a BroadcastReceiver on action "android.intent.action.BOOT_COMPLETED" in Manifest. Or call AlarmManager.cancel(...) and AlarmManager.setRepeating(...) on every launch. This way I may ber sure my timers work.
In Windows Universal I use triggers and background tasks. This works the same way with some limitations.
Now I'm porting my app to iOS, and quick look doesn't give me a way to register a function or class to perform quick checks (mostly less than a second) every 10 minutes while the app itself is not launched, and also I would like to register a function on device boot event. Is it possible?
Or should I keep my app running in background? I'd prefer not to do so, as my checks are lightweight and rare.
You can use background fetch for quick executions.
But there are several disadvantages:
Doesn't work in sleep mode.
You cannot catch device-launch event.
It will be dropped in 30 seconds.
I think in common case this is not analog for AlarmManager. Forget about it.
https://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Push notification can be used as a trigger. But, nevertheless, this is a server-side implementation.
In the guide above:
Check the box Background fetch in the Background Modes of your app’s Capabilities.
Use setMinimumBackgroundFetchInterval(_:) to set a time interval appropriate for your app.
Implement application(_:performFetchWithCompletionHandler:) in your app delegate to handle the background fetch.
Your callback event is performFetchWithCompletionHandler

Android - use a service as a timer?

I've read and re-read the documentation but I'm still now sure if using a service (and how) is the right way to keep a timer running.
I basically want to have a countdown timer, but I want it to run uninterrupted even if the app gets closed (and show up as an ongoing notification). When a certain activity in the app gets opened (resumed, opened, launched from clicking on the notification), I want it to be able to get the current value from the timer (no more frequent than once per second). If the app got closed, I still want the timer to be able to use/launch activities or other services (or access the database) of my app.
So if I understood the Android developer docs correctly, I should use a service that is started (because when started it should be able to do its thing even in the app gets closed) and bound (so an activity can get data from it). Then I searched Stack Overflow for similar topics and some people are recommending using IntentService (but can it send data to an activity?), or Handlers or even AlarmManager.
I'm really confused and I'd prefer to be able to pick the right approach from the start (rather than finish the app and then realize my approach wastes a lot of battery or something). The problem with documentation is it answers questions it thinks I have, so I have to ask a real person.
My suggestion is:
When user starts your timer save current system timestamp.
In your UI: Every N milliseconds just read saved value and compare it to current timestamp. This give you a diff = elapsed time.
You do not need any timer/service/alarm manager. Every time user has return to your app you just do step №2 to show elapsed time.

Android Timer Alternative

I'm looking for some timer alternative, since timer dies with app, is limited, and every timer launches own thread.
Sometimes I need to launch about 20-30 timers.
I need to set some event, in time, and when it comes display app screen. Is it possible?
This may or may not be possible depending upon your definition of "dies with app".
You can use AlarmManager to schedule PendingIntents to be invoked at specific times in the future. Those PendingIntents can launch activities. This will work if your app "dies" from ordinary causes.
However:
If the user force-closes your app via Settings, your alarms are unscheduled, and there is nothing you can do to stop this (nor do you have any alternative to AlarmManager that somehow survives this)
Please allow the user to determine whether or not you display an activity or raise a Notification at these times, as users may not necessarily appreciate having their game, navigation, video, or phone call interrupted by your activity.
You should use AlarmManager.
As CommonsWare says that there are some limitation of it, but that is ok, if an user force closes your application it means he doesn't want to use your application (any more or due to sort of memory)....
And I have a solution (but may be not the best), because you can not listen if user force closes your app, so one way is that you can re schedule your event on each start of your application. I know this is not a good solution but ..... we have no any other way yet
Here is a good example.

Android Communicate with AlarmManager

I am not sure how to describe my Problem. Basically I want to write an app, which reminds the user after a specific time (e.g. 1hr) of something. Unless he does not confirm the reminder, it will nag him every 10 mins, after the initial hour has passed.
Until the reminder pops up for the first time there will be 4 stages (eg. every 15mins), which should be shown inside the activity (eg with colors green, yellow, orange, red).
I implemented the reminder with a Broadcast Reciever and the AlarmManager, so far so good. But how can I check how long its been since the Alarm was set to find out in which stage I am? If the Activity is running in the foreground while the stage changes, the change should be made visible instantly. If the activity is started while the alarm is still counting down, the current stage should also be shown.
Anyone can point me in the right direction on how to do this in a good way, since I am still fairly new to Android.
Thank you.
[So far I basically followed this tut http://www.vogella.de/articles/AndroidServices/article.html]
You may want to maintain an int that represents the state of your counter. You can make it a member variable in your Activity, and you may want to persist it in shared preferences as well. To pass status change notifications from the alarm service back to your Activity, send an Intent. Your activity need not check up on the alarm counter; it can simply wait for the intents to roll in.

Which is better for repeated user notifications: A series of broadcasts, a started service or a bound service?

I'm currently developing an android application that will repeatedly ask a question to the user in randomly determined time intervals. This means it will wake up the device if nessecary, pop up an Activity, make a sound or vibration and let the user choose one of the options.
The user will be able to turn the series of pop ups on or off. The user will also be able to temporarily turn it off for a self-determined period of time. Lastly the user will be able to specify designated times of the day in which the series of pop ups will turn on or off automatically.
I already know how to schedule Activities and BroadcastReceivers with AlarmManager. I also know how to wake the device up by looking at the source code for the alarm clock on android.
My question is how to best implement it with the Android framework. When the pop up series start my application needs to randomly determine in which interval the next pop up will occur. When the time has come for the notification to be displayed. The Activity will pop up (already implemented) and immedeately the next pop up time will be randomly calculated. When the user has not answered the question in the pop up when it is already time for the next pop up, the application must know that. The application must also be able to determine when is has to start and stop its pop ups as specified by the user. At all these points something must be called.
I'm wondering if I could best do all this with a BroadcastReceiver receiving a series of different actions by Intent. Or should I use a Service doing all the work. And if I use a service is it best to send it different commands through onStartCommand() or should I rather bind to it and call the methods through the Binder?
I found the source for the alarm clock rather confusing on this matter and I'm unsure which method is the best. They all seem to have their strong and weak points.
Services can have 'states', but the system may decide to destroy it to free memory, thus losing this data. Scheduled BroadcastReceivers will be remembered by the AlarmManager, but they are 'stateless'.
With bound Services you can communicate both ways, but it takes some time to accuire the Binder. Started services can be given quick commands through onStartCommand(), but cannot directly communicate with Activities.
The decision remains hard...
The decision remains hard...
There is only one answer: use AlarmManager with a BroadcastReceiver. Nothing else can reliably wake up the phone. That BroadcastReceiver, in turn, should acquire a WakeLock and start up your activity. The activity can use android:keepScreenOn to keep the device awake while the activity is in the foreground; the activity should release the WakeLock acquired by the BroadcastReceiver in onCreate() after the call to setContentView(). The activity can schedule the next alarm based upon user input or lack thereof.

Categories

Resources