I am in the process of making an app that will be triggered by a system broadcast and would take time input from the user, after which the app should just run a timer and do a task after the timer is over. My questions are as follows:
Do I need to use a background task for this, or is this possible to be achieved without it, because I need the timer to run even if the app is closed in the app drawer.
If I do need to use a background task, what should I use, an AsyncTask, a Service or a JobScheduler?
I understand that a BroadcastReceiver will listen to any system broadcasts, and since I have registered in the Manifest, the app will start on any such system broadcasts. However, as soon as the app is started due to the system change, I need it to popup a dialog box which takes input in the form of time (HH:MM:SS), and after that a timer begins which runs for that amount of time and as soon as the timer stops, another task is done.
I also don't want the task to be a one-up, meaning that I want it to be to done every time the system receives the system change broadcast.
For what you want to do, you basically need three things.
A BroadcastReceiver for receiving a system broadcast. This component is essential. Also, you don't have to worry about it being a one-up thing. A registered BroadcastReceiver will continue to run it's onReceive() method until the BroadcastReceiver is unregistered by you or the system, or if you intentionally place code in to block it from activating.
An Activity to display the Dialog. Technically, a BroadcastReceiver can also display a Dialog, but BroadcastReceivers are meant for short and quick tasks, so it's not a good place for this. An Activity where you show a DialogFragment is the better option because compared to a Service, an Activity is really the component meant to display a UI.
An AlarmManager for counting down the time. Rather than creating a Service yourself to handle the timer, you should use the AlarmManager with exact time to help you respond to the amount of time that passed. You can also use a JobScheduler as an alternative to AlarmManager, since both are meant for executing code at a later time. Which one you choose depends on the task you want to do later on. Personally, you should also consider the new WorkManager, which is the better option in my opinion. Depending on what you need to do, it will internally use a JobScheduler or AlarmManager, which helps get rid of the deciding process for you.
Related
I am creating a notification app, which will alert user after they set a reminder notification. My current implementation logic is:
Create a Service, which starts running in background when user opens their app.
In onCreate() method of service, I am implementing a Timer task which will repeat after 5000ms interval and will call a method, which will check all reminders set by user and notify user if any reminder is set for current time.
I use broadcast receiver to run the service on Boot_Completed event, if in case user turns off their phone.
This implementation is working good, I have faced no issues with it, but my concern is that is this a good practice? Keeping in mind that service running and checking every 5 secs will consume battery. Also if user turns on Stamina Mode, Power saving mode or any such mode, will OS kill my service. Is there anything I can do to give priority to my Service not to be killed.
If there is any other more efficient way to implement this sort of task, I want to implement that in my project.
Looking forward for suggestions.
Much Appreciated.
best approach is wakeful intent service with alarm receiver as mentioned here
https://github.com/commonsguy/cwac-wakeful
all good but use AlarmManager.setRepeating() as timer. the intent come even if your app killed.
I started learning android i've been playing with it and so far so good but i have some doubts about Services, i started learning them today so by gently if a say something very wrong.
For example, i want my app to grab some information over the internet from time to time, this polling period is defined by the user, then the UI gets updated. I though about creating a Service that run lets says every 30 minutes, gets the information and updates the UI.
If i get it right:
An IntentService just executes an operation and stops by itself sending the result through an intent(right?), so i think it's not what i want.
A Bounded Service is most likely used when you want IPC or allow binding from external apps, which again i think it's not what i want.
I think a Local Service is probably what i need, using a LocalBroadcastReceiver to update the UI, how can i make it to run the operation every X minutes( Handler postDelayed, ScheduledExecutorService or Alarm Manager ? )
If i understand it right a Service if not bounded can run infinitely if it's not killed due to low memory problems, making it a foreground Service is the safest ?
Last thing and it's kind of a noob doubt, if the user leaves the application(Click Home Button or opens other app) the app is still in background but the activities are in "Paused" or "Stopped" mode will the Service still be able to talk to them ?
Sorry for long post and thank you.
Your requirement : after every x minutes, start a service, pull some date, update UI.
Solution :
Define or set an alarm for every x minutes, to trigger a receiver.
From receiver start the service.
In the service, start an async task to fetch the data in doInBackGround().
Once data is fetched, from onPostExecute() send a broadcast to your activity.
In the activity have a dynamic receiver registered for broadcast sent from service.
From dynamic broadcast receiver update UI.
From what you've explained I wouldn't personally use a service.
The Android docs on services explain more but here is a snippet:
http://developer.android.com/guide/components/services.html
A Service is an application component that can perform long-running operations in the background and does not provide a user interface.
You could perhaps looks at using an AsyncTask, especially given that you only want it to run whilst the app is running:
http://developer.android.com/reference/android/os/AsyncTask.html
This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
There is a good answer here on how to run an AsyncTask repeatedly at specific time intervals: How to execute Async task repeatedly after fixed time intervals
I need to keep service running to monitor changes through content observer.
I also need to know , Can my alarms set for periodic intervals can be erased ?
If yes then When ?
Can task killers erase Alarms for version onwards 2.2 ?
If you want to keep a service running, use Service.startForeground. Then the Android system won't kill it, except under the most extreme circumstances.
You need to supply a notification which is continuously shown to the user so that they know they have a service running which is potentially using resources. This seems to be a deliberate (and sensible) design decision.
So long as you do that, and so long as your ContentObserver actually works, there should be no need at all for you to wake up your activity or service code using AlarmManager. Your service should just continuously run and your code should be called whenever the content changes.
I see all the examples of AlarmManager being set by an Activity.
My question is this:
If my application sets a recurring AlarmManager, does that persist even after the application that started is is closed and removed from memory?
If not, how do I start an AlarmManager at a lower level that is started by Android at boot up and if it ever fails or dies or throws an exception is restarted without the user having to do anything?
Lastly, if the action I wish for the BroadcastReceiver to undertake has no visual components, do I still have to create a separate Activity for it? In my case I want there to be a background uploader that wakes up and looks into a folder and if it sees files in that folder, sends them off to the server. I don't need any feedback to the user.
So, my ideal would be to have a magical, OS based AlarmManager that calls an IntentService which just handles the uploading, but I'm unclear on how to get such an AlarmManager running in the first place.
TIA
Yes, AFAIK the alarms "survive" and keeps getting triggered, even after the activity that registered them ends. But they don't survive a phone reboot.
If I understands your problem correctly, I think you can achieve what your looking for by creating a project with a broadcast receiver that listens for android.intent.action.BOOT_COMPLETED intents and then (re-)register a repeating alarm, which in turns starts a (Intent)Service to do the uploading.
You don't need an activity, but you probably would want one anyway, to let the user temporarily disable the upload mechanism by checking off a checkbox, or something. It would probably also be nice to let the user choose the frequency of your alarm, i.e. how often the service should be started and look for new files to upload. This would also be a good place to register your alarm for the first time.
I agree with Nicolai that you'd have 2 broadcast receivers in your application :
one that re-register the alarm on boot
one that starts your service when triggered by the alarm
You could still have an activity but it shouldn't be started by the alarm receiver (hence the service) : instead, maybe launch a notification as you start your service, with the user having the possibility to launch the activity from the expanded message of the notification.
maybe also think about setInexactRepeating (instead of setRepeating) for your alarm, as well as using a worker thread to handle the long uploads (in case the user wants to use your activity in the main thread at the same time).
In my Android app, I have some data that needs to be synced daily but also needs to be updated every hour when a user is inside the app.
I have already implemented a service that gets called from an alarm for the daily update. Im having a problem with developing a strategy to do the hourly sync. I could use an hourly alarm too and fire the same intent, but since your app can be killed at any time, there would be no way to cancel it (and since they use the same Intent, doing a cancel would cancel ALL alarms including my daily sync, so that's probably not good).
The other option is to use a Timer that's set when inside the app, and have that fire my Intent when inside the app. Im assuming all Timers get cancelled when an app is killed right? But my app consists of several activities and I want the timer to work across all activities, how do I do that? I dont want to duplicate code - we're already using a subclass for Activity and ListActivity.
I have some data that needs to be
synced daily but also needs to be
updated every hour when a user is
inside the app.
The solution seems easy: drop the second requirement. Few apps are used continuously for hours on end, since people tend to use their Android phones for other things (e.g., phones), so your update-hourly-if-used-all-the-time code will probably never run.
I could use an hourly alarm too and
fire the same intent, but since your
app can be killed at any time, there
would be no way to cancel it
FWIW, your app will not be killed while it is on-screen. And, while it is not on-screen, you don't want the updates going hourly.
Im assuming all Timers get cancelled
when an app is killed right?
Apps generally are not "killed". We expect you to clean up after yourself when your activities are called with onDestroy(). If you set up the Timer with a daemon thread, you will need to terminate that thread.
But my app consists of several
activities and I want the timer to
work across all activities, how do I
do that?
Bind to your service from each of your activities. If it is started by your alarm Intent, have it do normal update processing. If it is started due to a binding request, just have it make sure its hourly Timer is running. When it is called with onDestroy() (e.g., after all activities have unbound), have it stop the Timer.
You might be able to have a Timer run in a background service (which get killed less than activities) but there is still no guarantee that Android won't kill your service either. And running something like this is the background might use a lot of battery.
What about doing the hourly sync in a background thread that get's created in onResume? And just save the last time the user did the sync, and if it has been > an hour just do the sync. Because I don't think there is any reason to eagerly sync data that the user is never going to see.