Repeating Task in Foreground service in Doze mode - android

I'm working on an application in which I have to do some repeating task at fixed interval (let's say after 2 mins) which should complete even in doze mode. My observations are mentioned below -
Doing repeating task using Alarms (using RTC flag) aren't accurate. Android system batches alarms. If we use RTC_WAKEUP then it is better than RTC, but it shows WAKEUP count in Android Vitals which is not good.
Jobschedulers are useful but will not work for lesser interval like 2 mins. I had tried Firebase Jobdispatcher but that is also not very accurate, I started Job with 2 mins Trigger time but it was varying from 10-20 mins.
Used Handlers and Timers for repeating task in Foreground service. In this scenario Foreground service continue to run in Doze mode but handlers and timer stops repeating task. I read about Handlers.postDelayed() and found that this is also affected by doze mode.
I don't want to acquire WAKELOCK for this repeating task.
Can someone please suggest me some better/clean way by which we can do short interval repeating task in doze mode?
For reference -
Android: What is the best way to make repetitive Background Tasks Android Oreo ready?
How does doze mode affect background/foreground services, with/without partial/full wakelocks?

Not exactly a direct answer but still - I needed to schedule an action every minute in my foreground service (give or take a second).
Fortunately I was capturing sensors in this foreground service too, I made onSensorChanged event check if the right time has passed and act if needed.

Related

Starting foreground service in doze mode

I'm developing an app which connects to a special device via wifi. I need to make status updates in a short interval, resp. keep the status of my special device in the app up to date. FCM is not an option. My idea is to give the user two options: Fast updates using a foreground service or "slow" updates using a periodical update mechanism to save battery.
My question is about the second option. The interval should be around five minutes. Using JobScheduler therefore is not possible. But even using the AlarmManager seems not to be an option because I'm not able to get network access during the doze maintenance windows.
I thought about using a WakefulBroadcastReceiver to receive the Intent by the AlarmManager, require a WakeLock and turn my long running Service into foreground by calling startForeground(). But it seems that the startForeground() method has no effect on the Service as long as the device stays in doze mode.
I read many pages about doze and services but have no clue how to solve my problem... Does anyone got an idea?
you should use GcmTaskService. You can schedule some interval for your operations and it would work fine even in doze mode, check more information by link
You can use setAlarmClock, but it is not recommended for your purposes.
Instead you can use setExactAndAllowWhileIdle with manual re-programming with an interval of 15 minutes.
Best way: GCM.

for aggressively repeated alarms, which is better Alarm or Service with Timer task?

I am trying to do an application that shows the user notification with options that user can choose:
Aggressively repeated: like every 3 minutes (does not wake-lock the device)
Highly repeated: every 10 to 15 minutes (does not wake-lock the device)
Repeated: every 1 hour
once a day
so for the first 3 options, (as a Performance and battery life) is it good solution to set up Timer and start a scheduleTimerTask within Service ? or should i set an Alarm from AlarmManager?
Service
Constantly runs in Background , will drain battery
Can be killed by android or user might go to setting and kill it manually
Will be killed if phone is switched off
service was basically meant to do background services like loading and
uploading data on separate thread, for your purpose AlarmManager is
useful and it will not be killed by android and probably will drain
less juice than service
It's better to use an alarm. A service can be killed by the OS.

Android: Scheduling applications for continued execution

I have gone through various discussion threads and tried multiple iterations to have my application scheduled to repeatedly run at fixed intervals. I have been successful too, but starting the thread to get understanding how things work.
I had tried the implementation with ScheduledExecutorService as well as TimerTask and both did not trigger my task at right intervals. But found success with AlarmManager.
Please lead me in right direction to understand why the timing did not work well with ScheduledExecutorService and TimerTask.
The app is required to perform a task on a regular interval. Say, my task takes around 5 minutes to complete, I would like to keep it scheduled so that it runs once in every 30 minutes. When I built the application with ScheduledExecutorService or TimerTask, I found that it does not trigger the task at 30 minutes, but it triggered at 1 hour or even more. So far, with Alarm Manager, it seems to be working fine getting triggered at around 30 minutes(slight variation is still found, but better than the other two).
When I built the application with ScheduledExecutorService or TimerTask, I found that it does not trigger the task at 30 minutes, but it triggered at 1 hour or even more.
More importantly, it will not trigger at all once your process is terminated, which can happen at any point and, from the user's standpoint, should happen quickly, to free up RAM for other apps.
Your trigger delays are probably due to the device falling asleep. Your solution would not only tie up the user's RAM, but also would require you to prevent the device from falling asleep, which is horrible for battery life.
AlarmManager is a far more appropriate solution, as it does not require you to keep a service running or otherwise have a process around. Just be sure to use WakefulBroadcastReceiver as the way you respond to your _WAKEUP event, as the device will want to fall back asleep.

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.

Questions about Alarm Manager behavior and wakelocks

I'm using alarm manager in my service to set non-waking alarms every 15 seconds to execute a certain task. I don't want to wake the phone up as the task isn't time critical, so i'm using the ELAPSED_REALTIME flag to set the alarm. Here's the code:
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 15 * 1000, intentRecurringChecks);
What I'm noticing in my logs is that the task is getting executed every 15 seconds. Does this mean the phone is staying awake even though it's screen has been turned off for half an hour? Is there a way I can be sure my application's not the one waking up the phone?
I've search about this topic but I can't find a proper answer.
Thanks for your help.
First, you shouldn't use AlarmManager for such timeouts. This is explicitly mentioned in documentation (read the bold part). It's better to use Handler based timers in your case. Here is an example: Repeat a task with a time delay?.
Second, when device is connected via USB, its not going to deep sleep mode. You should disconnect your device wait a minute or two. Attach it back and analyze the logs.

Categories

Resources