Invoke startService()/bindService() from Service to Service? - android

Is it possible to run startService() or bindService() from a Service to another Services?

startService() can be used even if you call this method inside a Service. So, it's possible to trigger another Service from the current Service. But you can't call bindService() to trigger another Service, it requires an activity to be bound and display the result in UI, such as MP3 Player. Once an activity which calls bindService() was destroyed, the bound-service will be killed by system.

Related

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

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().

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().

onServiceDisconnected() not called after calling Service stopSelf()

I have an Activity in which I start and bind to a download Service.
When calling stopSelf() in the Service, onServiceDisconnected() in the Activity is not called.
I would expect it to be called, since if the Service is stopped, all bound activities should be unbound.
What am I missing?
According to the official document, onServiceDisconnected() would be called if the service crashed or was killed. Link http://developer.android.com/reference/android/content/ServiceConnection.html
Called when a connection to the Service has been lost. This typically happens when the process hosting the service has crashed or been killed. This does not remove the ServiceConnection itself -- this binding to the service will remain active, and you will receive a call to onServiceConnected(ComponentName, IBinder) when the Service is next running.
Simply sending a notification to a bound client and calling stopSelf() (or stopService()) won't actually accomplish what you are trying to do. You have to call unbindService() in the bound client (and the service must have no other bound clients) in order to actually destroy the service.
There are two types of Services, "started" services and "bound" services. They are not mutually exclusive. If you started the service using startService(), you have a "started" service. If you start the service through bindService(), it is bound. If you bind to the service and also use startService(), it is both. So there are three possible options for managing a service's lifecycle:
1) Started Service:
you call startService() to start it; service will only be stopped by calling stopService() or stopSelf().
2) Bound Service:
you call bindService() and pass in the BIND_AUTO_CREATE flag. Other clients can bind and unbind to the service at will, the service will be automatically destroyed when all clients have detached. In this case, calling stopService() or stopSelf() has no effect.
3) Combo:
clients bind to the service and you have also called startService(). In this case, calling stopSelf() or stopService() will only destroy the service once all clients have detached. Likewise, the service won't be destroyed automatically when all clients have detached, until stopSelf() or stopService() have been called.
The documentation for the lifecycle for combo services says:
These two paths are not entirely separate. That is, you can bind to a
service that was already started with startService(). For example, a
background music service could be started by calling startService()
with an Intent that identifies the music to play. Later, possibly when
the user wants to exercise some control over the player or get
information about the current song, an activity can bind to the
service by calling bindService(). In cases like this,
stopService() or stopSelf() does not actually stop the service
until all clients unbind.
So in your case, you have a bound client. Calling stopSelf() doesn't forcibly disconnect bound clients, so you have to explicitly notify your client that the service wants to shutdown, and then your client has to call unbindService() before the service is destroyed. You can accomplish that in a variety of ways, most simply through a broadcast or an IBinder interface, or a messenger or AIDL if you are communicating with your service across processes.

How to create an android service that runs after the activity has ended

I have a android app that has an ongoing service for tracking a persons location. I want to be able to start up the service from within the activity and end it from within the activity. When the activity is running I need to be able to bind to the service and communicate to it via aidl. However I need the service to continue even when the activity has ended. I only want the service to end when the it is told to by the activity.
So far I have my activity and service and they can communicate through a aidl file. But at the moment the service ends when the activity does.
How do I get it to continue running when the activity has ended AND how do I rebind to it when the activity is restarted?
I have figured it out.
I was using the bindService method which created my service for me and bound to it (I need a binding), but if a service is created via a call to bindService the service only lives as long as the binding and so when calling unbindService, which I was doing when my activity was destroyed, the service itself also was destroyed.
However if you create your service with a call to createService and then call bindService you will bind to the already running service. Then when you come to unbind from it, it no longer destroys itself. The service will continue until you call stopService.
Then when you re-enter your activity you can check if the service is already running and if it is just call bindService other wise just call startService followed by bindService

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