Need to implement a timeout feature when application goes to background - android

I need to create a timeout feature when my app goes to the background for 5 minutes(anything that fires up onPause() except when activity is finishing). If the user goes back to the application then the timer should be cancelled.
Also, I need the timer to be not dependent on the time set in the phone meaning when the app goes to the background and then the user changes the time the application will still timeout within 5 minutes.
Checking out the documentation of the AlarmManager it states the following:
Note: The Alarm Manager is intended for cases where you want to have your application code
run at a specific time, even if your application is not currently running. For normal
timing operations (ticks, timeouts, etc) it is easier and much more efficient to use
Handler.

Alternatively, you could try setting up bound service - these can operate in background even if user toggles frontmost application. you can communicate with the service using Handler, just as you would do with threads.
the easiest would be to use sendEmptyMessageDelayed of predefined type and use call to removeMessages() once your app is back on top.

You should take a look at the AlarmManager. You can easily program your app to run at a specific time or every 5 minutes with a PendingIntent. You can cancel it with the same PendingIntent.
I don't know about the time dependency but it's easy to test.

in onPause() set an alarm using AlarmManager, like this:
AlarmManager alarmManager = getSystemService(Context.ALARM_SERVICE);
// Alarm time is elapsed time since boot (including sleep) plus 5 minutes
long alarmTime = SystemClock.elapsedRealtime() + 5 * 60 * 1000;
alarmManager.set(AlarmManager.ELAPSED_REALTIME, alarmTime, pendingIntent);
For the pendingIntent() you can use either a broadcast Intent or you can have it start one of your activities. Depends what you want to do when the alarm goes off.
NOTE: Using AlarmManager.ELAPSED_REALTIME ensures that changes the user makes to his date/time settings won't have any effect on your 5 minute timeout.
Make sure to cancel the alarm when your app resumes (in onResume()) and when it finishes (in onDestroy())

I wonder if the easiest solution wouldn't be to just set a value in sharedPreferences when your activity pauses and test this value again onResume. To avoid the value being corrupted by the user changing the clock you could employ SystemClock.elapsedRealtime() or SystemClock.uptimeMillis()

Related

Do you need to remove an alarm before setting new one

I have an Android alarmManager being set and a broadcastReceiver to pick it up, whenever the app triggers onResume, I am forcing a new alarm to be set.
So I'm wondering for best practices and considering good resource management, should I be removing the first alarm (if it hasn't triggered) before I reset a new alarm ?
Potentially if an alarm doesn't trigger, each time the user re-opens the app, is it creating more resource usage even if the alarm is for the same time ?
Yes you should cancel it when it is appropriate.
I suspect you will have a lot of wasted cycles otherwise. For Example,
App opens at Time T.
Schedule an alarm for T'.
Next the user opens the app again at some time, X seconds prior to T'.
You will then schedule an alarm presumable at another time T''.
However you will get an alarm firing in X secs anyways. If you ignore it, you are simply wasting battery if the phone had to wake in order to deliver the alarm.
If you create the same PendingIntent for your alarm, then the previous one will automatically be canceled when you set it again.
See AlarmManager.set(), PendingIntent.

Getting elapsed time from AlarmManager

Pretty new to android, so forgive me if this is a dumb question...
So, I'm making an app with a countdown timer that will ring periodically, and then again when the countdown hits zero - simple enough. However, I want the app to keep running even when the user closes the application or the phone is asleep, so that whenever the timer rings, the app will wake up and display an activity showing the time until the countdown is finished. To do this, I'll need to use a service, and lo and behold, the google devs made the AlarmManager service just for me! Sweet!
However, I noticed 2 things:
1) the AlarmManager class has no default constructor, so I'm assuming I can't just extend it and tack some logic on so that I can get all this done in one shot. Ok, cool - I'll just make a service that instantiates AlarmManager at the start, and implement my logic there.
2) In the documentation, I don't see any way of getting either the elapsed time or the remaining time from AlarmManager once it is running.
So, my question is: does this mean that I will need two timers that I start at the same time? Say, an AlarmManager to wake the phone up and call the activity, and a CountDownTimer contained in the service to hold the remaining time and call the alarm ringtone?
Thanks for helping out my clueless ass.
You could extend AlarmManager. However the common way is to get an instance of it, which is running as a system service.
Get the instance using Context.getSystemService(Context.ALARM_SERVICE) and you will be able to register your PendingIntent to that system service, which is independent to your own app. The PendingIntent can either start an activity or send broadcast with some Intent. You don't monitor the elapsed time constantly in AlarmManager. Rather, you calculate the time difference between the current time of your method call, and the desired time to fire your event. And then you set an alarm in AlarmManager with a PendingIntent representing the action you wish to take at that interval, or a time point.
On the other hand, if you want maximum flexibility, run your service as foreground service and listen for system broadcast like ACTION_TIME_TICK, which is fired every minute. Alternatively if you don't run service in foreground you could also run your service with START_STICKY, which guarantees that your service will be restarted after the system kills it (due to sleep or closing app). Think this as a background service that is constantly running. This provides you a lot of flexibility in your implementation.

TimerTask vs AlaramManager, Which one should I use?

I am working on an application which triggers an action (say toast message) every 10 minutes after the screen is ON and stops the action after the screen is OFF.
I have used TimerTask for this purpose.
Shall I start using AlaramManager instead of TimerTask or shall I keep using TimerTask ?
I know the difference between the two but can't figure out which to use.
Cant' agree with the nikis' answer
Timer and AlarmManager are solutions addressed to satisfy different needs.
Timer is still a "task" that means this is a thread of your application that means that some component of your application must be running on device to keep timer alive.
If you set timer for 10 minutes events - you can't be sure if your application will not be disposed by system in some moment. If device will be turned into the sleep mode your timer can be stopped. To prevent behavior like that you have to use PowerLock's and drain battery
AlarmManager is system service (runs outside your application) that means that the pending intent will be sent even if your application is killed after setting the alarm.
Some examples:
You have to blink some "led" on the view every 1 s - use Timer - you need it only when application is in foreground, there are short intervals - no point in using AlarmManager for task like that.
You have run some task once after 10 s - Handler.postDelay(); will be the best solution for that, and the job will be done on main thread (UI).
You have to check every 10 minutes if there is some new content on device that you are supposed to push to the server - use AlarmManager - your application does not need to be alive all the time, just let system to start job you want every 10 minutes - that's all.
In most cases you should definitely use AlarmManager, because (from the docs):
The AlarmManager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing. This guarantees that the phone will not sleep until you have finished handling the broadcast. Once onReceive() returns, the AlarmManager releases this wake lock. This means that the phone will in some cases sleep as soon as your onReceive() method completes.
Although you don't need to fire any event while screen is off, AlarmManager still saves the battery by grouping alarms, when you use setInexactRepeating (but this is not important for you, because your interval is 10 minutes). And moreover, it can fire an event is app is not running. I vote for AlarmManager, because it's good practice, but considering your conditions, you can leave Timertask.
BTW, you can also use Handler, which I believe will be the best choice.

Android-Checking current device time in background

How to check the current device time in background at regular intervals(say every 1 hour) even after the app is closed using startService() method?Thanks
You don't necessarily need a service, depending on what you want to do with the time you get.
As a general rule, to do something at regular intervals you can use AlarmManager.setInexactRepeating() (or setRepeeating() if you really need a perfect periodicity). Use the PendingIntent of this method to start whatever (BroadcastReceiver, Activity, Service...) when the alarm is triggered.

Best way to set repeating task

i have a method in my app that i want to be called repeatedly depending on what the user chooses. like if every hour is chosen by the user, the activity fires a method that is being called every hour. i would like to know the best way to schedule this repeated task.
i have been experimenting with Timers and Timer task, but for some reason it doesn't not seem to work when i use the java calendar class with it, like this:
Calendar c1 = Calendar.getInstance();
c1.add(Calendar.SECOND, 30);
updateTimer.scheduleAtFixedRate(cleanCompletedCache, c1.getTimeInMillis(),hour );
and from what i have been reading, Handlers are not suitable for this multi-repeating task. would i have to use an alarm manager for this and why won't the above code execute correctly? thanks
You want the AlarmManager and it's setRepeating or setInexactRepeating calls.
There you schedule an Intent to be delivered to your application, and write an intent receiver to process it. This way, the activation of your application is entirely the responsibility of the Android system, and your application does not need to run for the entire hour it is just waiting to activate.
If, for some odd reason, you would need your code running between timer invocations, you need to keep a background service running, but you'd still use AlarmManager to get the wakeup.

Categories

Resources