Does overriding Service.OnStartCommand put the service into the started state? - android

In the bound services documentation, it says
When a service is unbound from all clients, the Android system destroys it (unless it was also started with a startService() call). As such, you don't have to manage the lifecycle of your service if it's purely a bound service—the Android system manages it for you based on whether it is bound to any clients.
However, if you choose to implement the onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be started. In this case, the service runs until the service stops itself with stopSelf() or another component calls stopService(), regardless of whether it is bound to any clients.
Does this mean that simply implementing onStartCommand automagically puts the service into a started state when a client binds to it?
I've been looking for a way to guarentee that when a client binds to the service, the service is in the started state. So far, the only way I've been able to do it is by having the client call startService followed by bindService. But if the above is correct, then all I have to do is implement onStartCommand and the client is free to just call bindService.

I agree that the documentation is wrong. Simply implementing onStartCommand() changes nothing. Especially because you don't implement it, you override the method, because there is already an existing default implementation of onStartCommand()
When you bind to a Service, the Service isn't technically "started", it is just bound. onStartCommand() will not be called unless something calls startService().

Related

Can I stop the service which is started by bindService instead of StartService in android?

I have this "Activity 1" binded to Service. I started the service using
Intent wrapperServiceIntent = new Intent(mContext,BleWrapper.class);
bindService(wrapperServiceIntent,mBLEWrapperServiceConnection,BIND_AUTO_CREATE);
Can I stop this service using
stopService(new Intent(mContext,BleWrapper.class));
insted of
mContext.unbindService(mServiceConnection);
Is the above scenario possible?
From documentation:
When a service is unbound from all clients, the Android system destroys it (unless it was also started with onStartCommand()). As such, you don't have to manage the lifecycle of your service if it's purely a bound service—the Android system manages it for you based on whether it is bound to any clients.
However, if you choose to implement the onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be started. In this case, the service runs until the service stops itself with stopSelf() or another component calls stopService(), regardless of whether it is bound to any clients.
No you can not do it instead, you need to remove the bindings first.
The Android documentation says:
Note that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed until all of these bindings are removed.
Another thing, in stopService you need to pass mServiceConnection instead of creating a new intent.

Difference between onStartCommand() and onBind()

How is the "bind" action of the onBind() method different than just calling onStartCommand() ?
onStartCommand()
"The system calls this method when another component, such as an activity, requests that the service be started, by calling startService()."
onBind()
The system calls this method when another component wants to bind with the service (such as to perform RPC), by calling bindService().
I want to write a chat client service which receives messages from multiple users. Which function would be more appropriate?
The first (onStartCommand()) is called when your Service begins to do its work. onCreate() has completed and it is ready to get to doing what needs to be done.
The second (onBind()) is called when another Thread registers to connect to the Service so that they can communicate. You would configure or set up the means for the communication in here such as Interface validation or calls back to the registering Activity.
Binding allows you to tie the Service to the lifespan of, for example, an Activity. If the Activity completes then the Service is allowed to be released and can itself finish. The Service will last as long as there is something still bound to it.
onStartCommand() and onBind() are callback methods of Service class.
onStartCommand() called after onCreate() method of Service class first time.Next time whenever any other android component start same service then Service received new request in onStartCommand() method.
onBind() called when another Android components try to connect with already running Service by using bindService() method .Its used to pass some new info to service or try to make Service connection.
A bound service will end when it has no more activities bound to it. Binding also allows you to send additional commands to it via interfaces like AIDL. In your case, I think you'd want a bound service, as you likely don't want the service to outlive the activity.
In fact, if a component calls bindService() to create the service and onStartCommand() is not called, the service runs only as long as the component is bound to it. After the service is unbound from all of its clients, the system destroys it. So, by onBind() if the activity destroy your service would not trigger.
According to the official documentation,
when a service is started using bindService()
if a component(i.e Activity) calls bindService() to create the service and onStartCommand() is not called, the service runs only as long as the component is bound to it. After the service is unbound from all of its clients, the system destroys it.
and when a service is started using startService()
If a component starts the service by calling startService() (which results in a call to onStartCommand()), the service continues to run until it stops itself with stopSelf() or another component stops it by calling stopService().

Is it OK to call Service.startService() from within Service.onBind()?

I have a service which I want to make sure does NOT stop() when there are no longer any activities bound to it.
I understand that startService() is used to achieve this, but is it okay to call this from within the service's onBind() method?
Calling it from the activity seems like a hack to me, because the service know's best whether it wants to hang around after onUnbind().
The activities indicate the current state of the service and provide some control, so bindService() seems like the appropriate method to use here.
It should be fine to call startService() from within onBind(). If you have logic in onBind() that can determine that the service needs to stay up even if the client has unbound then that seems to be the logical place to do it.
I disagree with the answer that claims it is not recommended. The architecture you've described is making effective use of encapsulation. Clients only want to bind/unbind and they shouldn't have to know how the service is (internally) implemented. The service should control its own lifecycle.
Calling startService() from onBind() is not recommended. onBind() is meant for connecting to clients, you should not change the behavior.
Before a client wants to connect, let it call startService(), if service is already running, it will have no effect, client object can then bind. service will still be running when clients unbind. If service knows when not to be around it can safely call stopSelf() on itself and exit.

When is it smart to use bindService and startService

I would like to know when it is smart to use bindService and when to use startService.
For example:
If I use bindService with BIND_AUTO_CREATE, the service will be started and created automatically as is written here: http://developer.android.com/reference/android/content/Context.html#BIND_AUTO_CREATE
When is it smart then to use bindService and when startService? I really don't understand these two correctly.
You usually use bindService() if your calling component(Activity) will need to communicate with the Service that you are starting, through the ServiceConnection. If you do not want to communicate with the Service you can use just startService(). You Can see below diffrence between service and bind service.
From the docs :
Started
A service is "started" when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.
Bound
A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
You can read more here : Android Services, Bound Services
I agree with #Ovidiu Latcu but with one important note:
when using bound services, the service is ended when the activity that started it is ended, (if it is the only activity bound to that service).
So if you want to run your service at the background while the app is in the background,
(the activity is paused for example and not visible to the user) then you must start the service without bounding to it and communicate with it with BroadcastReceiver for example.

Binding to a service in Android

I'm a little confused on how binding to services works. I understand using Context.startService() starts the service and that bindService doesn't call onStartCommand. But my understanding is that if I use startService, I have to explicitly stop the service. But I want the service to die if there are no more activities bound to it.
My problem is that calling bindService never calls onServiceConnected(), so my Service binder object is null. Does the service have to be explicitly started in order to bind to it? If so, how does it know to terminate when nothing is binding to it anymore, and how do I know if it's started so I can know to use the bound object?
if you call bindService with BIND_AUTO_CREATE as flag the system will bind your activity to the service if it exists, otherwise if it doesn't exist the system will start the service for you and then it will bind your activity to the service. Furthermore if you start a Service in this way the service will remain active only if it has still some context binded.
this is from bindService():
Connect to an application service, creating it if needed. This defines a dependency between your application and the service. The given conn will receive the service object when its created and be told if it dies and restarts. The service will be considered required by the system only for as long as the calling context exists. For example, if this Context is an Activity that is stopped, the service will not be required to continue running until the Activity is resumed
and this is from ServiceLyfecycle
A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().
The answer is that I wasn't waiting for the service to actually be bound before using it, since it gets bound asynchronously
You should be setting up your binder in onBind and any generic setup in onCreate. The behaviour of starting and binding services is explained at http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle

Categories

Resources