Recently, I'm working on an app that needs to run a Service every day at a certain time.
To do this, I use AlarmManager.
My question is: After activating the AlarmManager (from the Service), can I destroy the Service, and the AlarmManager will still call me in time?
If not, is there any way at a certain time to send me BroadcastRecerver, without running a Service all the time in OS?
Would appreciate help
The short answer to your question: service can still be started from the alarm manager anytime the alarm receiver is able to run. The long answer: usually it's good practice trying to use job schedulers though. They can both decide a better time to run, while ensuring you have the necessary resources to run successfully, such as network or high battery among other criteria.
Alarm managers are only reasonably reliable before Nougat. It's been long announced that developers should stop using it, and start using job schedulers for most use cases. They are meant to replace both the alarm setup and receiver, and allow the phone to save more battery by putting the phone in doze mode for longer and waking up and doing multiple tasks all at once.
Even if you get alarm manager working on your particular phone google makes less and less reliable with each OS release. There are very specific cases where alarms are still the way to go, but unless you're certain to be in one of these try to use job schedulers for all devices running lollipop and later. You can still use alarm manager reliably for kitkat and older, where job schedulers don't exist. More details on: https://developer.android.com/training/monitoring-device-state/doze-standby.html
In either case I think you need to listen for phone's boot so you can register your alarm/job scheduler:
https://developer.android.com/training/scheduling/alarms.html
Job scheduler info:
https://developer.android.com/topic/performance/scheduling.html
For reliability issues: Android AlarmManager not working on some devices when the app is closed
Related
I'm having trouble deciding whether to run some recurring background work with Alarm Manager or Work Manager:
The work is going to consist of Room Database operations so I'll need access to Dao to complete my work.
It is going to be recurring at fixed intervals (hourly, daily, weekly, monthly, etc.)
I need to set a start date and time for the recurrence intervals.
the work will recur until canceled by the user
If the user is using the app when the work is supposed to be scheduled, I want the work to be done immediately. If the user is not on the app (app is in the background or device is turned off), I don't care if the work is done after the scheduled time as long as it is at least started by the next time the user opens the app.
the work needs to continue as scheduled after device reboots and app restarts.
For recurring background work, AlarmManger isn't suitable. As the name implies, it's intended to notify the system of an event at a precise time. Just like a physical alarm that wakes a person up even if the person sleeps, AlarmManager will wake up the device from doze mode which will result in more power usage. it is suitable for suitations like setting remainders such as for calender events which the users probably set by themselves.
On the other hand, WorkManager is intended to carry out background processing or work that would persist. Workmanager is much more efficient for recurring task especially as it allows you set constraints to determine when it should start or stop the background work.
check the link form the offical documentation on WorkManger:
workmanager architecture
tabular comparison between the two
It mostly depends on how important your task is.
https://developer.android.com/guide/background is a really good entry point to help you choose what you should work with.
WorkManager is the modern, universal approach of handling background work and it fits for most use-cases, it automatically reschedules work after a device restart or an application crash, and it is very efficient in terms of battery usage.
As WorkManager does respect Android's doze mode, it does not guarantee, that the work will be done exactly on time, though it does guarantee, that your work will be done within a certain time frame.
On the other hand, AlarmManager is capable of running work precisely on time. But this means that the device will wake up when your work scheduled with AlarmManager is coming due. This will drain battery and your app will probably show up as battery-draining in the Device Health board.
But as stated in the article above, prefer using WorkManager if possible. AlarmManager should only be used for e.g. a time-sensitive calendar notification.
In my app I used Alarm manager for time scheduling. For that I used Alarm Manager API .
I am using setInExactRepeating() method for repeat my alarm but it's not triggering my alarm when my device is in idle condition. Also sometimes it delays to triggering alarm.
For my app its important to trigger the alarm at the exact time in repeating mode also in idle condition.
Please help how can i resolve this issue, I also learned about Job scheduler and Work manager but these have not a feature like alarm manager to set alarm at exact or repeat.
Thank You
You probably can't do any with repeat because on higher android there is a limitation for repeating (i think 15m) for better performance and battery saving and Alarm manager on higher android isn't the best.
Even if you manage to do so and make your app it will probably be killed by performance controller applications or even android OS itself. and I don't suggest investing your time in it because of this.
There were few tricks to trick the android OS and get your app running but I think it will be really messy to code that. the best thing to work is the same WorkManager as you say
My app has a background service running that gets users current location and update it to a server every five minutes. To run this location update process continuously, I use alarm manager to set its next execution time from the service itself. However, when I install the app in my Nokia 6 running Android 8.1 it works for some time and if I keep the phone idle for some time, my service will get killed with the next alarms by the application also being cleared from system alarm manager. My guess was that the idle time makes the phone enter doze mode. However, I don't understand why the alarm managers got cleared. To my understanding, the doze mode should open up maintenance windows periodically to execute any pending tasks.
To mitigate this issue, I tried to apply a JobScheduler service on top of AlarmManager, which runs every 15 minutes. Purpose of this jobscheduler was to re-start the service which has the alarmmanager in it, so even if it gets killed and the alarm is cleared, jobscheduler would re-up the service.
After I tested this patch and keeping it for some time to go into idle mode, it resulted in getting both JobScheduler Service and Service which has the alarm in it killed with the scheduled jobs and alarms getting cleared from the system.
It is said in the Android documentation that we can use JobScheduler to mitigate its background execution limitations. And to test this out I forced killed the two services when I tested the app, but the already scheduled job did not get cleared, and it made the service with the alarm run again successfully. I don't understand the reason for this behavior, although the Evernote guys give an explanation that could match this scenario in here Android Job by Evernote
Any ideas for this abnormal behavior?
Test Environment Details
Device : Nokia 6 (TA-1021)
OS : Android 8.1.0
You would not be able to run background services long running in Oreo as there are behaviour changes, now Oreo to optimise system memory, battery etc, it kills background service, to solve your issue you should use foreground service.
Have a look at Background execution limits https://developer.android.com/about/versions/oreo/android-8.0-changes
A suggestion from me, if you can use FCM then go for it, becasue apps like WeChat, Facebook uses it, to deliver notifications and they don't face any problem...
Hope this helps in understanding the issue....
In Doze more, the alarms do not get reset, but get deferred to a later time. You have two mainstream options here:
Use either setAndAllowWhileIdle() or setExactAndAllowWhileIdle(). However, these too can fire at the maximum frequency of 1 time per 9 minutes. So you'll have to decrease the frequency at which you get location in your app.
Use a foreground service by way of showing a foreground notification. Everyone does that (apps like Uber, Google Maps etc). That way, your service won't get killed, and be treated as though you have an app open.
I'm currently facing the same issue and doing the same workaraound like you do. That is, setting the Jobscheduler to a periodic job to launch my Foreground Service every 15 min in case it is getting killed for whatever reasons like a killed task. This works like a charm on pre Oreo Versions.
For Oreo the only solution I am awared of at the moment is, to allow the app to autostart in the settings. Under installed apps that is. Then it should work like pre Oreo again.
What Ive heard but not tested yet, is to set the setPersisted(true) option in the Job Scheduler.
Let me know if that helps
I assumed currently DOZE mode not allowed to background service so you need to find a way that DOZE mode will not affect on your app.To solve your issue you should use foreground service. or make some battery setting. Any way my better option is you should go with Firebase Cloud Messaging
Short version: Alarm Managers no longer work in the background in Android 8 (Oreo), Android people are saying to use Job Scheduler as the alternative, but the job scheduler doesn't allow specific times of the day like Alarm Manager did so well.
Longer version: I have a "reminder" notification that goes off at a specific time of day set by the user. Up to this point, I've used an alarm manager to post the notification at the set time. This sends the user a notification to the user even if the app is in the background. But in Android Oreo / 8.0, this isn't allowed anymore. Most background services, receivers, etc. are fairly limited. I've set up a job scheduler, but doesn't allow for an exact time. Periodic settings in the job scheduler cannot be set ahead to a specific time. So despite Android's claims that job scheduler is the intended replacement for alarm manager, it doesn't seem to do one of the key things people use it for, setting at a specific time of the day. Does anyone know of a way to do this in Android Oreo in a way that it works even when the app is in the background?
I've tried sync adapters (need the alarm manager for that too!), handlers (nothing for a specific time), playing around with the different settings for the job service (periodic, minimumLatency, etc.), resetting the notification after the last one finished (can't do that in the background either!), and still haven't found a valid solution.
Is there anything that works like the job scheduler (i.e. Android 8/Oreo lets you run in the background, but that lets you schedule an exact time of the day, on a daily basis?
Alarm Managers no longer work in the background in Android 8 (Oreo)
I am not aware of anything regarding AlarmManager that changed in Android 8.0. Feel free to point to documentation or an issue tracker entry to validate your claim. Or, file your own issue with a reproducible test case.
But in Android Oreo / 8.0, this isn't allowed anymore.
Sure it is, at least as well as it worked in Android 6.0 through 7.1. Doze mode and app standby have screwed with AlarmManager, but that's not new to Android 8.0.
Most background services, receivers, etc. are fairly limited.
They can still raise a Notification, which is what your question indicates that you want to do.
Does anyone know of a way to do this in Android Oreo in a way that it works even when the app is in the background?
Use AlarmManager. Since you are writing what amounts to an alarm clock app, use setAlarmClock().
one solution i can suggest may be solved your problem.
you should start job schedule 15 minute repeater mode and call every minute one broadcast where you can check this current time is your specific time of day or not.
if yes then send notification.
In my Android app I need to do some work every time the user plugs their device. For this purpose right now I use a BroadcastReceiver, which starts my IntentService to do the work when the user plugs the device and stops it when the device becomes unplugged.
Right now I'm thinking of using JobScheduler for Android 5.0+, but what I'm seeing is that with JobScheduler, I would have to schedule my job within the app, by calling
JobScheduler.schedule(JobInfo);
But this is a problem to me, because I want my job to run every time the user connects their device to the charger, even without the user having to open my app.
For this reason, I think one way would be to schedule it the first time the user opens the app, and then always force reschedule, since I cannot trust on the user opening my app every day (which, due to the nature of my app, certainly won't happen).
So, should I stick with BroadcastReceiver or use JobScheduler for Android 5.0+?
And in the case of using JobScheduler, should I schedule my job only once and then always return true in order to force rescheduling?
Thank you.
So, should I stick with BroadcastReceiver or use JobScheduler for Android 5.0+?
Use JobScheduler, this can improve your app’s performance, along with aspects of system health such as battery life. Also, JobScheduler persists through device reboots and supports batch scheduling by which the android system can combine pending jobs thus reducing battery usage. Moreover, you can do distinguish between android versions thus using JobScheduler on Lollipop and up, and AlarmManager on older versions.
And in the case of using JobScheduler, should I schedule my job only once and then always return true in order to force rescheduling?
Now, there are 2 ways to do this :
As you guessed, scheduling your job only once and always returning true in jobFinished() - this should do the trick.
Upon completing a job (originally scheduled by you by calling JobScheduler.schedule(JobInfo)), you schedule another job by calling the same. This will schedule consequent jobs once each job is about to be completed.
Jobscheduler runs in the background and persists through reboots so you should be fine.