I want to create Event Reminder App, I search and found that I need to use a service and broadcast receiver.
But it is not clear for me what is the role of each components ?
As I understand-but I am not sure- that the App needs an Activity that when starts, it runs the service ( which check the current time with times are stored persistently , for example in database !). when the two times match , the service create a broadcast, and our broadcast receiver receives it and create Alert.
My questions are:
Does this inception is correct ?
How to make the service running and always check the time ( do we need some infinite loop?!!)
thanks in advance,
Activities and Services can be killed off without notice anytime system decides it's low on resources. There is no guarantee that your Service would run all the time. Also, if phone is in sleep mode, your code stops executing.
So:
The premise is wrong, for the reasons stated above.
You cant guarantee that Service would be running all the time.
For your purpose you should be using AlarmManager. It is garanteed to call your code when alarm is triggered. Also important - AlarmManager survives device restarts.
Related
I need to create a service that runs alongside the android app,irrespective of which screen of the app the user is on.
The app is a chat application so when the device is offline the service should queue up all the messages that are being sent offline and when the device is connected it should sync all messages.
I have written code for the job scheduler to sync data automatically when the device is online but while the app is active i would like to handle this manually.
Creating a Long Running service.
Operating system still can terminate the service in low memory and possibly other situations. There are 2 ways to overcome this:
If you are implementing the service, override onStartCommand() and return START_STICKY as the result. It will tell the system that even if it will want to kill your service due to low memory, it should re-create it as soon as memory will be back to normal.
AlarmManager .A system service, which will execute actions periodically. That will ensure that if your service will be terminated, or even the whole process will die(for example with force close) - it will be 100% restarted by AlarmManager.
Thank you.
You can do this by simple following steps:
Create Simple Service and after first launch of app just start at splash screen.
In Service after getting one data you can call another request.
After that you can create one broadcast action globally which will always call every network changed.
At background you can sync again data and saved it to shared preferences or as per your your requirement.
For interval you can also using AlarManager.
A part from this you can simply create Service using JobSheduler in this you can assign job and time as well.
Refer link :
https://developer.android.com/reference/android/app/job/JobScheduler.html
Hopefully this logic will helps you.
You have to use a intent service with sticky instead of service for this which will be executed in a queue and do your work. And since it is a intent service it will be started automatically after sometime, when system kills the service process.
I'm looking to build something similar to Google's field trip application. The key attributes that I'm looking to prove out are:
A background "job" that runs every X minutes and checks the user's location and make a webservice call(this question doesn't really concern the location part)
The job should run even if the user exits the main application.
The background job should automatically start up after the device reboots.
After a reboot the application should not show up on the "recent/history" screen
My reading has brought me to a number of different classes/APIs from broadcast reciever of on boot, to regular services, to alarm manager, etc. It seems there are multiple ways this could be made to work, I'm curious what the community recommends as a high level approach?
You would definitely want to use a broadcast manager to get the boot event.
As far as polling for location goes, it sounds like you would want to use a Service and start it once you received the boot event.
Services
You could then use an event bus like Otto to communicate your events to wherever you need.
As far as the timing goes you could use a job manager to run things at various intervals, or just simply create a runnable and have it run as often as you like. As long as you keep it in the service, you should be able to control the length that it will run just fine. Regardless of whether or not the app is closed.
I think you may divide your solution into two parts :
Starting the app or the service after the device re-boot process completed by defining a Broadcast receiver that has the following action :
And on the "onReceive" method of the broadcast "do your task " start the service that listen to the location service updates.
For the part of listening to the location updated every x minutes, you would better use the alarm manager to "wake up" the service every x minutes, and every service sets the alarm for the next call.
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'm developing an app designed to transform an android phone into a remote device running without user action. At the time the app is made by an Activity that sets AlarmManager to execute a service (class inside project) every X minutes.
All this works OK, but occasionally after 5-6 DAYS continuosly running the application crashes (currently I don't know why, because i can't get the phone now). It isn't a connection problem (I know) and the phone is still running (plugged into AC). The only thing that i can suppose is that the application is down.
I don't think that this is due to a bug, because the prew debugging doesn't give me any errors.
So I must suppose that android has killed the activity (system needs more memory?) and as the image explain there is no way to back it up.
But I have a doubt: in my application the activity doesn't matter, because all the work is done by the service. The service itself is called by an Alarm Manager and in the time between two calls the service is terminated by StopSelf().
In my case the system may kill my alarm manager service schedule?
What can I do to have the service start up by Alarm Manager forever?
(ATTENTION: currently there is yet a WAKE LOCK but this consider only the execution of the service! I hope that you have understand that the service is called each x minutes by alarm manager and than terminated...i want to perform this operations for an indefinite time)
[I haven't posted the source code because is too long]
Lork,
After wrestling with a similar issues myself, I may have some pointers for you. I assume that you are using your Android device as a sort of remote ‘embedded controller’, which performs its functions with minimum user interaction. I believe that you are 95% there and just need to make some slight architectural changes. As you have not provided code, I’ll just explain in abstract terms rather than give code examples.
CommonsWare is correct that you need to use AlarmManager, but I suspect you already knew that.
A couple of background comments first, just to make sure that everything is understandable.
Alarms created by AlarmManager exist at the system level, that is they can exist beyond the lifecycle of the activity and application that created them. If you set an alarm but don’t want it to go off if your app changes state (for example after it has been destroyed), then you can cancel it using alarmManager.cancel(pendingIntent) – just create the intents and alarm manager with the same parameters and Android will match the alarm).
Similarly, BroadcastReceivers are registered at the system level (at least if they are declared in manifest.xml) and can exist beyond the lifecycle of the activity and application that created them. Again if you want to ensure that a BroadcastReceiver does not fire in response to an event occurring after your app has changed state (for example after it has been destroyed), you need to explicitly unregister in it code. If it was registered programmatically then use context.unregisterReceiver(broadcastReceiver); if it was registered statically in the Manifest its not so easy – you will have to retrieve the receiver using PackageManager and ComponentName (see: Android - how to unregister a receiver created in the manifest? ) - and remember that you will need to re-enable the receiver if you need it again.
You say you have already set up your alarm. Make sure you specify ELAPSED_REALTIME_WAKEUP or RTC_WAKUP for the alarm Type to ensure that it runs even when the phone is in ‘sleep’ mode.
You also say you have already created the associated BroadcastReceiver to handle to alarm event. The BroadcastReceiver should do a minimum of work, so you should handle any processing in a separate thread or by launching a Service. You opted to launch a Service and terminate it using stopSelf() when it has finished, so that it doesn’t use up system resources. So far so good.
This is fine when the app is running, however as you require something that runs reliably for an indefinite period, you need to ensure that you manage the 'exception' situations where it has paused, the device is ‘sleeping’, the app has crashed/terminated, or the device has rebooted (and any other exception scenarios you may think of). Here are the issues I have identified that you need to address:
First: WakeLock is only guaranteed for the duration of the onReceive() method of the BroadcastReceiver. After it has terminated, the device could go back to ‘sleep’ even if your Service has not started or even completed, so you need to create a WakeLock, pass it to the Service and release it before you stop the Service. (Note: for your application, you require a PARTIAL_WAKE_LOCK). Be very careful using WakeLocks – make sure you only hold a WakeLock for the minimum required time and ensure you release it, as it’s use can lead to excessive battery drain). See http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html for an example of using WakeLocks.
Second: If you reset your alarm in code (rather than defining an automatically repeating one), do this in the OnReceive() method of the BroadcastReceiver or as the first thing in the Service you have launched – this will ensure that the alarm repeats, irrespective of the state of the application or device.
Third: Make sure that any Contexts you use are going to be non-null values. You can dynamically fetch the context in the Service using getApplicationContext(). Otherwise this can be achieved by EXPLICITLY passing the Context from your application to the alarm and make sure it is passed all the way through the BroadcastReceiver, and associated threads and Services. If you have statically stored Context in your application so you can retrieve it anywhere, then this will return a null value if the application has terminated. If you use the Context (for example to retrieve a resource, access a database etc), and it is null, it will cause a null pointer exception and the Service or BroadcastReceiver will crash. I believe this is the most likely reason for your Broadcast receivers not to be working when your app has terminated.
Fourth: You may wish to make references to ResourceIDs (e.g. R.drawable.icon) in your Service or BroadcastReceiver fully qualified (. R.drawable.icon) or generated from the passed Context. I haven’t yet found this to be necessary, but I suspect it may be prudent.
Fifth: Implement a separate BroadcastReceiver to handle a device reboot scenario (ON_BOOT_COMPLETE event). You could get this receiver to re-launch the app if appropriate or it could launch a service to check that your app is supposed to be active, set up any required parameters and set up the relevant alarms, then terminate it using stopSelf(), or just set the alarm again and let that receiver handle it all. Remember to ensure the service has a WakeLock for its duration and to release the WakeLock when it is complete. If you don’t just relaunch the app, or a Service (declared as part of your application) then you should also statically store the correct Context as a class attribute in your BroadcastReceiver, if you need it, so that it is available to access resources.
A couple of other things you may wish to consider:
As your set up is remote, I would seriously consider storing any persistent data in SQLite database tables. This will ensure that data is recoverable between application terminations and device reboots, without having to regenerate it.
If your application communicates with a server service, consider using push notifications for server initiated communication, rather than have the app periodically poll. Push Notifications can also be used to ‘wake up and launch services and apps’, so could be used as part of a remote mechanism to query the status of the device and your application. This approach is also more power efficient and timely.
Post information to LogCat at key points in your code for debugging. If the application terminates, then adb stops tracking the source code running for the receiver and service, but LogCat continues to function, so can be used to check the path through the code and variable values.
Other people may have better ways to address these issues or some other pointers (I would certainly be very happy to see other input), but I hope these ideas are helpful and good luck!
The point behind using AlarmManager with a service is to start up a service that will run briefly, then the service goes away (e.g., an IntentService). If you are going to try to have an everlasting service, you do not need AlarmManager, and your service will be shut down by Android after some period of time.
If you rewrite your app to not need an everlasting service, but rather use AlarmManager as it was intended, you should have better survivability.
I believe that what Lork wants to achieve is similar to something I am also wrestling with.
He wants the alarm manager to trigger a broadcast receiver that will handle the alarm, even when the application it is part of, has been terminated (for example by the Android OS).
For example: The application sets an alarm, with a type of ELAPSED_REALTIME_WAKEUP or RTC_WAKUP and has a Broadcast Receiver to handle it when it fires, via an Intent which references the application context and the Broadcast receiver class. The receiver is declared as a in the application manifest.
Under normal circumstances, when the application is running or paused, when the alarm goes off, the Broadcast Receiver is triggered, waking up the device and resuming the application as necessary, and the alarm in handled.
However, if the application has been killed (for example by the OS), then the alarm will still go off (as it is still registered) but the Broadcast Receiver will not be triggered and LogCat shows a null pointer exception, (I assume because the reference to the application is no longer in memory). This will occur, even if the Context has been passed.
Am I (and I assume Lork) missing an easy strategy here? Or is it not possible? Can a broadcast receiver exist on its own and trigger the app if necessary?
One, imperfect strategy I have been toying with, is to move all the app data access into a Content Provider, and have a separate low profile app which just implements the broadcast receiver – triggering a service to do the work and accessing the application data it requires via the Content Provider. This would still be subject to being terminated by the OS, but would be less likely.
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).