What is the best practice to create a scheduled notification at some point in the future?
I have found a way using a Service that is triggered with a PendingIntent via the AlarmManager. In the onCreate() method of the Service I create the notification. This seems a bit like abusing the service to do something it is not supposed to be doing.
Is there another less cumbersome / more elegant method of achieving the same end? (The use case in question is giving the user a daily reminder to do something with my app)
What is the best practice to create a scheduled notification at some point in the future?
AlarmManager.
This seems a bit like abusing the service to do something it is not supposed to be doing.
Ummm...why?
Is there another less cumbersome / more elegant method of achieving the same end?
Setting an alarm requires a total of 3 to 4 Java statements, plus one for any extra you package into the Intent. Processing the alarm in a BroadcastReceiver to go raise a Notification regarding the "daily reminder" should be another ~20 lines of code, plus one entry in the manifest.
Related
I have a foreground service and while it's active I want to run some events based on specific exact time that you a user previously set, it can be one time or it can repetitive every day for example.
I don't want to use AlarmManager because it triggers system events and you need some permissions for it, I have a running service anyway so why would I use something like this... So it should lifescoped to the service
I don't want to use Handler and its func postDelayed or launch and delay of Coroutines because it's like inventing a wheel, especially when you need to implement logic for repeatable events for a specific time.
So I'm looking something as local broadcast messages but with time configuration like in alarm and I could use set date/time instead of millis delay logic
I might need some more clarifying details to give better advice, but the following should give you an idea of the possible options and their pros and cons.
As much as AlarmManager might seem like a pain, it is probably your best bet for something like this, especially if the events are spread out over a longer period as the question hints (e.g. once a day). The alternative would be to use something like Handler, Coroutines, or a TimerTask inside the service. In addition to introducing the complexities of managing repeating events (as you mentioned), all of these require that the service is constantly running and presumably doing nothing other than waiting to fire an event, which is wasteful and likely not precise over a long period of time. Further, the service could be killed by the system and then you'd have to recreate all the timing logic, whereas AlarmManager scheduling is more persistent.
If your foreground service really is active doing other things for the entire duration in which you want these events to fire, or if the requirement is that the events fire if and only if the service is already active, then these options could be back on the table, but I'm not sure without more information.
If exactness is not an issue, you could potentially use OneTimeWorkRequest or PeriodicWorkRequest; see this documentation.
If your main concern with AlarmManager is using date/time scheduling instead of milliseconds, that shouldn't be an issue as most temporal classes provide easy ways to convert to milliseconds.
Overall, because of the inherit difficulty of precise scheduling, a system-based implementation like AlarmManager is best if exactness is the goal, and other options will incur an unnecessary waste of resources.
I have used background service in for updating tasks like playing with web server frequent times(sending Geo-Location data or send/get web data time-wise) in my android apps and also I have faced many problems(slow process, application hang) for this.
But In my current application I have used the AlarmManager followed by PendingIntents for some tasks which worked well.
So I think its good if I replace each updating tasks which use service with AlarmManager followed by PendingIntents.
Is it the right way or I am going doing a big mistake ?
All kind of suggestions are appreciable.
Thanks in advance.
Services and alarms scheduled with AlarmManager serve different but complementary purposes at times. When you schedule an alarm with one of the set methods, the alarm will be triggered at the specified time and you should handle it on a BroadcastReceiver. This means that your handling has to be responsive and cannot have asynchronous operations. According to the docs:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active. (...) Anything that requires asynchronous operation is not
available, because you will need to return from the function to handle
the asynchronous operation, but at that point the BroadcastReceiver is
no longer active and thus the system is free to kill its process
before the asynchronous operation completes.
In case you want to handle more complex operations, it is advised to start a service for doing so. Even if you use the more recently available goAsync() call on the receiver, you are still expected to be responsive:
This does not change the expectation of being relatively responsive to the broadcast (finishing it within 10s)
So it ultimately depends on what you are trying to achieve, when to use each of these or combine their use.
I don't tell that using Alaram Manager is a big mistake..
Right now to run the background services there are only few options upon which the easy and partially reliable one would be AlarmManager.
Though sometimes the Alarm Manager is not 100% reliable on looking into other categories for doing these operations (like Asynchronous Thread and delay looping techniques) are much more complex and not that much reliable to do the background services.
When we compare the pros and cons of the techniques needed for background services AlarmManager wins the race.
I prefer AlarmManager would be the good option for these kind of background services upon thinking the options open right now to complete the tasks in background.
Hope that Google will comeup with a better solution to handle the background services.
In my app I would like that a certain method of mine (call it toSched) will run at a given time in the future (I'm using Timestamp for knowing when).
How can this be done, and is it possible to do it even if the phone is turned off (assume there is enough battery) ?
*I know I should use AlarmManager but I'm not sure how
You want to use the Android Alarm Manager. You do it by creating a PendingIntent (which is what you want to run) and then calling the set method. Checkout this stackoverflow post for more info.
What most people do is create a PendingIntent that is a broadcast. Then they create a broadcast receiver to receive that broadcast and do what ever is supposed to be done. Here's an example of "calling a method" to start an activity. But you can just put your own arbitrary code in the receiver to do what ever random task.
There's several ways of looking at this. One alternative (the one I think you're looking for) is discussed in this Stack Overflow thread:
How to set a timer in android
Another is to make sure your program gets invoked when you need it to:
AlarmManager
... or ...
cron
I'm implementing an background process that will update information my app uses.
I only want this process to update say once a day, if the process gets data newer than what it had before I want to present the user with a notification, exactly like twitter/gmail does.
I want the update process to run automatically, even when the main app is not open.
Is a Service the best way to go? I've been reading quite a bit about this, I figured a service running all the time for something that is only going to do work once a day seems a little overkill.
However I notice google run service for friendlocation and google+ services continuously on my nexus.
I've look into starting my service via the AlarmManager so its only started when required.
Some posts also suggest using the Handler class, I don't think this will work.
Just looking for the best practice here.
I figured a service running all the time for something that is only going to do work once a day seems a little overkill.
Absolutely.
I've look into starting my service via the AlarmManager so its only started when required.
This is the correct answer.
If you only want your code to be invoked if the device is on, implement an IntentService, do your work in its onHandleIntent(), and have AlarmManager start up the service on your desired schedule.
If you want your code to force the phone to wake up, you can do that, but you will need to use a _WAKEUP-style alarm, and you will probably want to look at my WakefulIntentService, designed to handle this pattern.
I am writing an app which needs to periodically check the server for new messages and notify the user. I have seen some examples using AlarmManager to hit a BroadcastReciever which seems like the right thing to do, but i cant seem to get it to work.
Can anyone show me a step by step tutorial for this sort of thing (repeating alarm which triggers some kind of background code that fires a Notification)?
TIA
Here is one complete example: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/
The pattern this example uses, and one that I've found that seems to work well, is to use a boot receiver to setup the AlarmManager (and of course also check to start the polling from your main Activity too, for the case when your app is installed and the system is not booted) and have the AlarmManager send an Intent for another receiver: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealBootReceiver.java
And then from the AlarmReceiver start an IntentService:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealAlarmReceiver.java
From your IntentService then make your network call to poll for data, or whatever you need to do. IntentService automatically puts your work in a background thread, it's very handy:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealService.java
Check the docs for these classes too, a lot of into in there.
The caveat with this example is that it does not deal with the wake lock gap (the excellent CommonsWare code does that if you need it), but it may give you some more ideas about how to potentially address the "poll using AlarmManager and Service" stuff.
UPDATE: the code is now here: https://github.com/charlieCollins/android-in-practice