I have an Activity that starts a service. When the activity is closed, I want the service to continue running in the background. I have a couple of questions here.
Will closing the activity screen cause the activity to actually stop? Or do I need to forcibly stop it to cause it to stop?
If closing the screen does cause it to stop, then I assume I need to use startService to start it. Is that correct? If that is the case, is there a way to get a handle to the running service next time the activity starts? If it is not the case, then I can just bind to the service.
When your Activity is no longer visible on the screen, it is stopped. Stopping an Activity bound to a Service does not stop the Service. However, you'll want to make sure you unbind from the Service when your Activity calls onDestroy() to make sure you don't have any dangling handlers and suchlike.
You can rebind to a running Service the same way as you did the first time. Sending an Intent to start a Service that's already running doesn't create a second instance of it, so that's safe.
A good way to start a Service like you're describing is to start it using the Context.BIND_AUTO_CREATE argument to your call to bindService().
The details of all of this can be found at the Android docs about bound services. It can be a little confusing at first. Follow the tutorial code closely since it sounds like your problem maps well onto the sample they provide.
Related
Just trying to clarify my understanding of how an IntentService is managed by the OS once terminating states have been reached. By terminating, I mean when the current activity is destroyed or the app process is killed, as per the following documentation:
https://developer.android.com/guide/components/activities/activity-lifecycle
Given the comment
Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask
at https://developer.android.com/training/run-background-service/create-service;
I feel as if:
1) A started IntentService is unaffected by the activity lifecycle. Is this correct?
2) If (1) is true, will it continue to run indefinitely even after a terminating state is reached, up to some point that it either stops itself or the OS decides to stop it?
In my particular situation, I'm using an IntentService during app startup to query APIs, grab content, and then add a new (landing) Page to the Xamarin.Forms navigation stack (this would be equivalent to starting a new activity).
This leads me to my next question...
3) What happens if the app is already in a terminated state when it comes time to the IntentService creating a new Activity? Surely the Activity can't be added to the navigation stack as it no longer exists once the app is terminated?
Yes, a started IntentService is unaffected by the Activity Lifecycle. Actually, all Services outside of bound Services are unaffected by the Activity Lifecycle.
An IntentService will continue until it reaches completion of it's work, the application is destroyed, or if the System decides to kill the Service due to the changes in the Android 8.0 background Service rules.
Your use of terminated state is too broad... If the Application is already terminated, then nothing will happen because the IntentService would have been terminated already too. If it's the Activity that launched the IntentService that was terminated, then nothing happens, since by default, an IntentService has nothing to do with Activities, even if it's the one that started it.
For the last question, it really depends on how you choose to communicate the result of IntentService to an Activity.
If you're using a BroadcastReceiver, then nothing will happen because an IntentService will fire the broadcast without any problems, but the Activity won't be able to receive the results since it's terminated.
But if you're simply creating a new Activity, then you can simply use startActivity() with the result data added to the Intent. Though, I doubt the user will be happy to see an Activity suddenly open on the screen when they're no longer in your app. Starting a new Activity has nothing to do with a previous Activity, since any instance of a Context can start an Activity.
Honestly, based on your question, it sounds like you're very concerned with an IntentService and it's connection with the Activity that started it. If that's the case, you really shouldn't be using an IntentService, since that's not really it's purpose. It's not meant to have a connection with an Activity. It's simply meant to do work and finish.
Instead, a bound Service would be a better option since it has a direct connection with the Activity that started it.
There is some long processing that need to be completed, so I put it in a service. The activity must be able to connect to the service, show the user current results from the service. So I start the service with start Service and later call bind Service (with BIND_AUTO_CREATE) as in LocalService from http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle. I want it to run until its job is done, and then self stop, even if client is still connected to it. (or determine the client to unbind) Is any way to do it with the sample LocalService?
I was considering passing a handler to the service so that it can send messages back to the activity, but I don't want the activity to get leaked. I am just getting used with services, so maybe I am misusing something.
EDIT: The workload consists of several threads, synchronized and run in parallel, so I guess is not a good candidate for intent service. Some data analysis is done in background service, and when the user restarts the activity that started the service, it should display some graphics according to current values computed by background service. All background processing is triggered at the beginning, and need only inspection later on, when activity connects to it. Android should not be able to stop the service. When the job is finished, the service should be able to terminate even if the activity is connected to it.
I just recorded a callback with the service. If the activity is not connected to service, it sets the callback to null. In this callback I call stopService() and then finish() on the activity. I am not sure that it is the best method, but it works fine for me.
If you want a service to be stopped when it is finished, I think what you are looking for is IntentService, they work as services, but run in another thread and when they are completed they dissappear.
Check this out
EDIT: NickT link is better, check that out! :)
I am wondering what is the best way to keep a service running while the application is running (may be in background) and then the service stopping when the application has ended (the application in this case has completely stopped, not in the background).
Another sub-question is: How to stop a service when application stops?
I realize one solution is to use BoundServices but is this the best way or good enough?
For example if an activity binds a service and then the system kills the activity and brings
it alive again then how will the service behave? Or are there other issues I am not aware of?
What would be the best way to implement this? Thanks.
Check out http://developer.android.com/guide/components/bound-services.html.
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.
You have two options to start the service:
1. bindService() to activity
2. startForeground() and bind while it runs
Option 1 will only run as long as the activity is in view and the runnable active. (example use would be to use service to download a file)
Option 2 will run as long as the application is running (even when the activity is in the background) This option requires that your service be listed in the notification bar.
You can have a service stop itself by calling stopSelf(int) (I dont think this works if a activity is currently bound) or you can call stopService() from an activity.
As for the system killing the activity question.... Without knowing what your service will be handling its hard to give advice on how to handle this situation. For the most part a service running in the foreground will be the last resource the system will try to reclaim. If the system kills the activity the services onDestory method will be called where you should do some clean up so that the next time it starts you can continue in a safe manor.
http://developer.android.com/images/service_lifecycle.png
Firstly, sorry for my English if it's not enough good. I'm having some problems in my application.
Starting, my app has multiple activities and one service which works in background since the first activity execute it. If I press back button on my root activity, I exit from the app but the service continue working. Then, I go into the app back, and the service work perfectly. My problem comes when I press a button to exit the application (there, I stop service and finish the root activity mainly) and then exit without any problem, when I want to enter the app again, the service is started, but if I want to change to another activity (which doesn't have the serviceConnection) my service get called onDestroy() method without any reason for that. I don't have how to continue, because the usual way to execute in this case is the service go on working as the first case.
Thanks a lot.
There is for sure a reason why onDestroy gets called.
In the first section of 'Services' in the developer guide, you can read the following:
Multiple components can bind to the service at once, but when all of
them unbind, the service is destroyed. (link)
So, if all components unbind from the service, the service will get destroyed. When you enter the activity that is not bound to the service, the service will be destroyed.
I'm wondering why you don't want your service to be destroyed since you don't need it in your 'another' activity?
Hello Android Gurus
For API Level 7 and Above-->
I am badly struck trying to figure out a solution for the following problem:
I have an activity which i would use to Kick start an Service. This is an infinite loop service which can run forever. I would like to disconnect the Service from Activity and at a later point of time i will call the activity again which should tell me the current state of Service and i can Stop the service.
Is something like this possible. Right now my Service is Sticky and i am not able to Close the activity as Service is running for ever and i am also not able to Stop the service from activity.
Code samples would be of great help!!! Thanks in advance...
Multiple questions:
You can disconnect/reconnect from the Service using bind. Unfortunately the best advice to give there is to carefully read the documentation for Service at http://developer.android.com/reference/android/app/Service.html: look carefully at the Local Service example, as it demonstrates what you need to do to bind/unbind to a sticky service.
To stop it, once you've bound you can call stopSelf.
Start the service non sticky from the Activity.
In the service control the flow logically, say calling onStart() to keep it running.
Call onDestroy() when you have to stop.