Binding to Service in onCreate() or in onResume() - android

I want to know what is the best place in an Activity to bind to a service?
I saw examples doing it in onResume() and also in onCreate(). I was asking myself if it is not a problem putting it into onCreate(), because in onPause() I will do a unbind to the service, so I don't get a serviceConnectionLeak, if I leave the activity. Now if I press the Home Button and then switch to the Home Screen, the Activity will unbind from the service, when I go back to the Activity from the Task Manager, then onCreate() will not be called and if the code is trying to access a function from the service I will get a NullPointerException. If I bind and unbind only in onResume() and onPause() I don't have this problem. Am i right?

I would generally recommend doing this in either onCreate()/onDestroy() or onStart()/onStop(), depending on the semantics that you want:
If your Activity wants to be interacting with the Service the entire time it is running (for example maybe it can retrieve some data from a network for you and will return the data when ready and you want to allow this to happen while in the background so if the user returns you will have the data ready), then onCreate()/onDestroy() is probably appropriate. Note that the semantics here is that the entire time your Activity is running it needs the Service, so if this Service is running in another process then you have increased the weight of it and made it more likely for it to be killed while in the background.
If your Activity is only interested in working with the Service while visible, then onStart()/onStop() is appropriate. This means your Activity will unbind from the Service when the user leaves it (and it is no longer visible) and connect back up the next time the return and it is re-started and resumed.
I generally wouldn't recommend doing bind/unbind in onResume() and onPause(). These generally won't decrease significantly the amount you use the Service (and thus your overhead), and in fact, because a pause and resume happens at every activity transition, this is a code path you want to keep as lightweight as possible. Doing it here can have other unexpected negative consequences: for example if multiple Activitys in your app bind to the same Service, when there is a transition between two of those activities the Service may also get destroyed and recreated as the current Activity is paused before the next one is resumed.
Also these pairs (onCreate()/onDestroy(), onStart()/onStop(), onPause()/onResume()) are intended to be the proper pairs for acquiring and then releasing resources (such as binding to Services, registering receivers, etc) to ensure that they are correctly acquired prior to being needed and released (and not leaked) when no longer needed.

What you say is correct. In most cases you will want to register in onResume() and unregister in onPause(). If you use onCreate() and on onDestroy() you will still be registering for updates when you are paused, which is being a bad citizen. If you register in onCreate() and unregister in onPause(), when you resume the task the registration will be gone, which is almost certainly not what you want.

Related

Should an Activity unbind from a started Foreground Service in onPause()?

If an activity wants to bind to a started foreground service, should it bind in onCreate() and unbind in onDestroy() or bind in onResume() and unbind in onPause()?
The content of the activity is dependent on data stored within the service, so it must be connected to display correctly. Is there any advantage to the latter option?
Since setting up the ServiceConnection takes some time, binding to the Service in onResume() may be way too late for your app to work smoothly. In addition to that, onPause() will also be called e.g. when you show an AlertDialog, so unbinding there means you'd have to "re-bind" as soon as the dialog is dismissed and - again - wait for the ServiceConnection to be up and running.
The documentation on Bound Services states
You usually pair the binding and unbinding during matching bring-up
and tear-down moments of the client's lifecycle, as described in the
following examples:
If you need to interact with the service only while your activity is visible, you should bind during onStart() and unbind during
onStop().
If you want your activity to receive responses even while it is stopped in the background, then you can bind during onCreate() and
unbind during onDestroy(). Beware that this implies that your activity
needs to use the service the entire time it's running (even in the
background), so if the service is in another process, then you
increase the weight of the process and it becomes more likely that the
system will kill it.
So in your case you can use onStart()/ onStop()

How to receive and process location changes when an Activity is paused

I am looking for a bit of app design advice.
I have an app that connects to the Google Location Services and tracks location coordinates it receives. These are displayed as a path on the UI.
When the screen times out and goes blank then this Activity will, of course, shut down as per the normal Activity life cycle.
However - I atill want to record the co-ordinates coming back in each onLocationChanged event from Location Services, but, of course, the Activity has paused so it cannot do that.
I don't particularly want to prevent the screen from blanking in the Manifest (and thus the Activity would never pause). Though I believe it would still pause if, say, a phone call is received etc.
My solution would be to start an IntentService in one of the Activity pausing events (either onPause, onStop or onSaveInstanceState) to receive Location updates, and then when the Activity restarts, collect the data from the Service and close the Service down.
Would this be an efficient and correct way of achieving this, or is there some Android black art that I don't know about? If so, is IntentService the correct way to go about it (or should I use Service)?
Proberly a normal service that gets restarted by an alarmmanager is an better idea.
In order to tie up loose ends, I'll add my own answer to this now I have implemented something.
My solution in the end was not an IntentService. This was because I thought that the IntentService would consider its work to be the actual setting up of the LocationService and once that work had been completed then it would shut itself down rather than hang about waiting for LocationService 'pings'.
Therefore, I implemented a normal Service, but I bound it to the calling Activity. I also set up a callback to the Activity. This way when a 'ping' was received I could process it and pass back the data directly to the Activity. Also, the Service would remain alive as long as the binding was in place. I clear the binder when the Activity is destroyed.
This worked perfectly....HOWEVER
I then discovered that the reason that the LocationService 'pings' were not being handled in the Activity was bacause I was disconnecting the GoogleAPIClient when the Activity onStop was called. Having removed this, the Activity processed the 'pings'even in its stopped state, so no Service was required anyway.
Therefore the correct answer to this question is... Activity should continue processing in the background (unless it's destroyed for memory management purposes), so check you're not stopping stuff in your 'shutdown' handlers onPause onStop etc. Then you won't waste time writing services like I did!

Event on launch/stop of visible part of application

Stackoveflow!
I have an application with sticky background service and visible part, consisted of several activities.
I need to track start and stop of visible part (all activities).
For example:
When user starts MainActivity, Service receives LocalBroadcast that tells it to start something.
When user rotates screen, Service must not receive anything.
When user goes to SecondActivity, Service again must not receive anything.
When user closes ALL ACTIVITIES, Service gets LocalBroadcast telling it to stop something.
If I use Activity. onCreate and onDestroy, or onStart and onStop, I get events related to lifecycle of single activity. Also I get events related to screen rotation.
I also cannot use Application. onCreate or onTerminate, as they will not trigger because of service running in the background.
I need to track real start and stop of entire application except service.
See: http://developer.android.com/guide/components/bound-services.html
When the last client unbinds from the service, the system destroys
the service (unless the service was also started by startService()).
So each Activity should bind() to the service, in onCreate, and unbind() in onStop/onDestroy
Now to fix the problem with the orientation changes, you can check for isFinishing in the onStop/onDestory callback
(see: How to distinguish between orientation change and leaving application android)
and also put some flag in onSaveInstanceState callback, so that in the following onCreate you can check for the existence of that flag, and act accordingly (refresh the binding, or avoid calling bind() again)

Stop Service in Activity onDestroy

Can I safely stop a Service in my main Activity's onDestroy method? I know that onDestroy is not guaranteed to be called, but I also do want to keep my Service running until the app is destroyed.
I'm thinking that maybe in all situations where the activity is destroyed, the service would also be destroyed?
You can stop a service in the onDestroy of an activity, but to do it successfully requires either:
Running a Service in the Foreground
A foreground service is a service that's considered to be something
the user is actively aware of and thus not a candidate for the system
to kill when low on memory. A foreground service must provide a
notification for the status bar, which is placed under the "Ongoing"
heading, which means that the notification cannot be dismissed unless
the service is either stopped or removed from the foreground.
For example, a music player that plays music from a service should be
set to run in the foreground, because the user is explicitly aware of
its operation. The notification in the status bar might indicate the
current song and allow the user to launch an activity to interact with
the music player.
or Managing Bound Services
A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely
In all your activities, manage any resources you have created within that activity and with a null check, close them down. Like you have in your service class. If you want to override the parent onDestroy, place your custom code before super.onDestroy.
There's more detail about this here.
but I also do want to keep my Service running until the app is destroyed.
The activity can remain on the stack in the stopped state and will not be destroyed until more memory is needed. This means that there is no fixed time that the service will continue to run until the activity is destroyed.
Activity Lifecycle
If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.
The entire lifetime of an activity happens between the first call to onCreate(Bundle) through to a single final call to onDestroy(). An activity will do all setup of "global" state in onCreate(), and release all remaining resources in onDestroy(). For example, if it has a thread running in the background to download data from the network, it may create that thread in onCreate() and then stop the thread in onDestroy().
To ensure that all your resources are cleaned up, you could either call finish() on the activity, or end the service in the onStop() method or use a timer in the onStop(), that will end the service or destroy the activity after x time.
The problem with calling finish() is that if the use navigates back to the activity quickly, it needs to be recreated. The problem with using stop() is if the activity is restarted the service will need to be restarted. So a timer could be a way to keep the activities natural state preserved to allow user navigation, but it would need to be stopped if the activity resumes in onResume().
For protected void onDestroy ()
Perform any final cleanup before an activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
Yes it is safe to do it in onDestroy. Because before killing your activity background service or forground service that is bound to component will get killed by system as priority for service running in background is lesser then component you are interacting with.

Message when Android App is closed

I am porting an iOS App to Android, and am having a little difficulty with the terminally.
I want the App to sync when starting/coming to the foreground (i.e. the user selects the App) and when the App goes to the background (e.g. when going to the main screen and start using another App.)
Is there an easy way to do that in Android?
I added onResume() and onPause() to my Activities, but this will be triggered when the activity resumes or pauses, not when the App as a whole pauses (and results in a lot of sync each time the user does something).
Update:
The Sync operation is a Service which is called when the App needs to get new/updated information from the server. As such, this needs to be done when the Application is started/resumed by the suer (after inactivity for some time) and it needs to do this when the user actively stops using the Application.
when an activity goes to background,
onPause() -> onStop()
methods will be executed in sequence, if activity is partially visible, only onPause(), if activity is completely invisible by another activity, onStop() method will be executed after onPause().
onDestroy()
method will be executed if you either called finish() or when there is no enough memory in the system and system destroys it. You can't rely onDestroy() method unless you call finish() method.
It's best to use onStop() method to save your data.
nr4bt has a valid point and depending on your required functionality, a good option.
A global approach would be to start a Service when your application starts.
Make this Service responsable for your syncing operations with suitable callbacks to your active Activity.
Make this Service aware of your alive/paused/stopped Activity's. When the last one is finished -> Do your final sync and kill the Service

Categories

Resources