Our Application has a service which starts a timer to schedule a task every 4 hours.
But the phone often goes to sleep when the screen is off.
I don't expect the task to run when the phone is sleeping.
But I want that it can be run immediately if the phone has slept longer than 4 hours.
TimerTask task = new TimerTask()
{
#Override
public void run() {
//do something
}
};
new Timer().schedule(task, 0, 4*60*60*1000);//period=4 hours;
I have done some tests that show if then phone has slept for more than 4 hours and when it wakes up, the timer's period didn't add the past 5 sleep hours and it can't run the task immediately.
Its period time just calculates the phone's wake time.
I have studied Timer.java, and know the timer's delay mechanism is to use thread wait(), that is the reason.
How to make a cyclic time task that contains the phone sleep time?
I think there is no need to use an AlarmManager, because the task doesn't need to run when the phone is sleeping.
Thanks in advance.
Instead of using Timer, you need to use AlarmManager without the wakeup option set. If you do this the alarm will trigger the next time you wake up the phone after the 4 hours..
Check out this tutorial: http://www.techrepublic.com/blog/software-engineer/use-androids-alarmmanager-to-schedule-an-event/
Related
I have a requirement, where my android app needs to check for location every 15 min and update it to SQLite DB. This process should happen even if app removed from background. I tried all the following ways, but none of them are working when app running for long time.
Runnable function with a foreground service. Below is the example
mHandlerTask = new Runnable() {
#Override
public void run() {
doCheckLocation();
mHandler.postDelayed(mHandlerTask, 60000 * 15);
}
};
mHandler.postDelayed(mHandlerTask, 60000 * 15);
This is working fine, but if screen turned off that runnable is not triggering. I think it's because of doze mode.
Work manager with Periodic Work Request: This is also not triggering when device goes to doze mode / screen turned off.
Alarm Manager: This has few functions setExactAndAllowWhileIdle(), setAlarmClock() for triggering at exact time. But the battery consumption is very high and phone gets heated up if I'm using setAlarmClock().
So I wanna try with a wake lock. When screen getting turned off I acquire it. I'll release it when screen is on. But wake lock is going to drain the battery, and most likely OS can kill my app.
Can anyone suggest a better way to solve this problem?
WorkManager and AlarmManager are in fact most efficient ways for scheduling some tasks in your app, but you just have requirements that aren't battery-efficient and won't be ever... both location tracking and "waking up" device every 15 minutes will cause high battery drain and I doubt you can prevent this
I have a react native app which makes a call to a native android module I have written. This native module starts a service in the foreground showing a notification to the user. I have done this because I want my service to run even when the app goes to the background or the screen display is turned off on the phone. Within my service, I am scheduling 2 tasks using the ScheduledExecutorService. Below is my code from the onStartCommand in my Service class.
The "runScanTask" is scheduled to start at 0 seconds and run every 13 secs after that. The "stopScanTask" is scheduled to start after 8 seconds and run every 13 secs after that. This works perfectly when my screen display is on. However, when I turn off my display, the jobs either stop running altogether or run at intervals which are completely random. Is there a way to get them to work correctly even when the display is turned off?
final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> startScanFuture = scheduler.scheduleAtFixedRate(runScanTask, 0, 13, TimeUnit.SECONDS);
ScheduledFuture<?> stopScanFuture = scheduler.scheduleAtFixedRate(stopScanTask, 8, 13, TimeUnit.SECONDS);
Runnable stopScanTask = new Runnable() {
public void run() {
Log.d("main", "STOP BLE SCAN");
}
};
Runnable runScanTask = new Runnable() {
public void run() {
Log.d("main", "RUN BLE SCAN");
}
};
When your screen is off, your device enters Doze mode as along as the CPU is not doing anything. Do one of the following solutions:
1- Acquire a partial wake lock on your service's onCreate, but it's bad to the battery.
2- Use AlarmManager's setAndAllowWhileIdle or setExactAndAllowWhileIdle . (minimum period between tasks 9 minutes when deep doze is active)
3- WorkManager (minimum period between tasks 15 minutes)
4- JobScheduler (minimum period between tasks 15 minutes)
5- Android-Job library.
See this article describes the dilemma you are facing.
Recently, I have been working on scheduling repeated tasks in background threads in Android application. I started with AlarmManager but due to its inaccurate triggers at specified intervals, I decided to use other JAVA and Android APIs.
I started with Timer and then ScheduledExecutorService and lastly ScheduledThreadPoolExecutor.
The problem with Timer is that it does not always run all the background tasks at right intervals. I had used it to run 3 background repeating tasks out of which only 2 were getting triggered. The third task was triggered after a couple of hours and to catch up with all the previous misses, it was triggered within 10ms (although the interval was 5 mins)
ScheduledThreadPoolExecutor is more accurate in triggering the repeated background tasks. But the problem with it is that it does not trigger the background tasks when the device is in sleep mode (screen off). The same is the behavior with Handler.postDelayed() which pauses the execution of tasks when the device is in sleep mode.
Now, I have reached a dead end. I am looking for a solution that could help me run my background tasks concurrently and without any interruption due to device going to sleep mode.
Please advice.
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.
I'm making an app that starts a Service that sends SMS message periodically under specific conditions. It all works, but I have problems to run the job (check conditions + message sending) periodically every minute when the phone is in "standby" (display turned off). With screen on it all works without problems.
I tried using java Timer and TimerTask, but when the screen is off nothing works and when I turn it on, all skipped task are executed in a row (for example, if I turn off the screen at 20:00 and turn on it at 20:30, TimerTask is executed 30 times at 20:30).
I tried also with Handler using Handler.postDelayed method. In this case nothing is done, and when I turn on the screen skipped task are not executed.
So, how can I run a Runnable every minute also when device screen is off???
You can try the AlarmManager
http://developer.android.com/reference/android/app/AlarmManager.html