I have built an application which implements a number of broadcast receivers and registers them within a service based on user settings. The service is bound to an activity which calls some of its methods.
When a broadcast receiver is called it starts the service (or calls onstart of the service if it is already running) and passes it a string telling the service what to do. My problem is when the activity is destroyed (back button) the service is also destroyed which in turn kills the broadcast receivers.
I know I can register the receivers in the manifest which would mean doing a check when they are called to see if the user has selected that option. However one of the receivers critical to the application is 'android.intent.action.HEADSET_PLUG' which can only be registered programatically.
So I guess my question is, is there a way to keep this broadcast receiver active when the service is destroyed?
If not can anyone see a workaround for this issue?
Thanks,
Rob
My problem is when the activity is killed the service is killed which in turn kills the broadcast receivers.
If by "killed" you mean the user terminated your app with a task killer or "Force Stop" in the Settings app, then "killed" is the appropriate verb. However, your whole process is "killed" -- it does not follow the chain of events that you describe here.
If by "killed" you mean the user exited your activity via the BACK button, that is because you elected to bind to the service, rather than start it. If you want the service to continue executing past the lifetime of the activity, you must use startService(), and ensure that there is some path by which the user can indicate that they no longer want this service, so you know when to call stopService().
So I guess my question is, is there a way to keep this broadcast receiver active when the service is killed?
No.
If not can anyone see a workaround for this issue?
Start your service, instead of (or possibly in addition to) binding to the service.
Related
I'm trying to implement an app that times how long my phone screen is on throughout the day using a broadcast receiver.
I'm declaring Action_Screen_Off/Action_Screen_On in my broadcast receiver since I can't declare it in my manifest, and I've been debating on the best way to handle storing the amount of time that my screen was on.
Since I can't declare it in the manifest, Should I declare the broadcast receiver inside of the onCreate in my activity? My worry with that is, if my understanding is correct, is that my receiver would then be tied to the lifecycle of the activity and I would only be able to store the on/off times whenever the activity is active.
The whole point of the app is that it's working in the background, and then displaying graphs of usage once an activity is in the foreground.
This led me to think that a Service might be the best bet the handle the Broadcast receiver, but Google seems to now be recommending that we don't use background services, only bounded and foreground services.
How can I make sure that my app is receiving the on/off intents, without the activity that declares the receiver being in the foreground, and the receiver not depending on the lifecycle of that activity?
You need a background Service for this functionality. Your Service doesn't need to actually do anything, but it needs to be active all the time so that you have something to anchor your BroadcastReceiver to. In onCreate() of your Service, create an instance of the BroadcastReceiver and register for the screen on/off events. Make sure that you return START_STICKY from your onStartCommand() in your Service. This will ensure that the Service is always active, and Android will restart the Service if it kills off your process (for whatever reason). The BroadcastReceiver can just write the timestamps of the on/off events to a file, SQLite database or SharedPreferences and your Activity can then read this data and show the graphs or whatever.
Say I have an Activity that launches a Service using startService() when user presses a button. The service is stopped using another intent in startService() when user presses another button, or it can decide to stop itself. The service wants to run forever, so it returns START_STICKY from onStartCommand(). While the service is running, it connects to some server and receives messages. Activity binds to it and, when bound, displays those messages.
Now, when the Activity is started after an OOM kill, it doesn't know if the Service is started. One can use a static field set in onStartCommand() to tell if the Service is running, but that's prone to backfire sooner or later. Moreover, the Service can be started by the system after the activity has been launched, so using a static field is not an option at all.
The cleanest solution I can come up with is using SharedPreferences to store the state of the service. This is going to fail to be good when the service is killed between SharedPreferences.setBoolean("running", false) and stopSelf(), but such a thing will probably occur rarely.
Also I can try to bind to the Service at all times. This would be very ugly but still not impossible.
Any other solutions? Maybe the very idea is wrong in some way?
I have a feeling i already know the answer to this but im not sure. Im using a broadcast receiver to intercept incoming SMS messages.
I register the receiver the typical way using the registerReceiver function and when you unregister the receiver you use the function unregisterReceiver function. I keep a global broadcast variable to load and unload the receiver as needed.
If the app closes, like the user actually closes the application and i don't unregister the receiver in the onDestroy method which i know is bad practice, would there be a way to unregister the receiver the next time the app loads? Could i create another instance of that broadcast receiver and then unregister it?
If the app closes
You can say that your UI is in the foreground or not. And you can say that your app's process is in the foreground, the background, or terminated.
It is unclear what "closing" would equate to.
like the user actually closes the application
A user can move an app's UI and process to the background (e.g., press HOME). A user can destroy an app's UI and move its process to the background (e.g., press BACK from the last running activity). A user can terminate an app's background process (e.g., swipe the app off of the recent-tasks list). A user can force-stop an app (e.g., pressing the Force Stop button for the app in Settings).
It is unclear what "the user actually closes the application" equates to.
would there be a way to unregister the receiver the next time the app loads?
Either you have a reference to your BroadcastReceiver object, or you do not. If you do, call unregisterReceiver() on some Context, passing in that BroadcastReceiver instance. If you do not have the BroadcastReceiver instance, you cannot unregister the receiver. If your process had been terminated between when you registered the receiver and now, that receiver is gone and is effectively unregistered.
I want to monitor network connection changes. (I know how to do it)
I did not use manifest file as I don't want my closed app to be awakened for connectivity changes. So, I register my custom BroadcastReceiver within my main application object (not in activity).
If I did that in my activity, I could unregister it onStop or onDestroy.
As I don't do this in activities, what happens when app is terminated (forceably by the system or killed cleanly by user with pressing back button (for eg.)? (I won't know when the app is terminated so I can't unregister it manually.. Should i?)
Will registered receiver still work? Will the app get awakened? Will it be cleaned completely and safely?
You should unregister it onStop and onDestroy.
That would take care of all your use-cases.
Since you are using the Receiver dynamically in your activity, and not from the manifest, it will only receive the intent if the Receiver has been registered.
So if you register onResume and unregister onStop and onDestroy, it will only receive intents as long as your activity is visible to the user in the foreground and at no other time.
I have an activity that starts a service in a seperate process via the android:process attributes of my service.
My service's onStartCommand() function returns START_STICkY.
I kill my activity's process through swiping it away via the recent apps button, and the service process restarts.
I want to know if there is a way to keep the service running when the activity process is killed.
I want to know if there is a way to keep the service running when the activity process is killed.
No, there is no way to keep the service running. Because,
Closed by the user via the Running Services screen in Settings.
Closed by the user via a task killer.
Closed by Android to free up memory in times of need.
Keep the service running is BAD idea.
But you can do,
--> you can restart you service using BROADCAST RECEIVER.(when incoming call, BOOT complete, SMS received.. etc, use this depend on your requirement)