Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to force onStartCommand() being called before onBind()?

I am trying to create a sticky service that is bindable to (I need to run potentially asynchronic operations in the background on some data that the service holds). To do this, I need to be sure that onBind always runs after onStartCommand. Is there any way to guarantee this?

like image 230
pstobiecki Avatar asked Jun 29 '13 20:06

pstobiecki


2 Answers

From your requirements, you probably don't need to bind to your Service. Then using an IntentService would suffice, as this service will stop itself after its work is done.

Taken from the docs:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

An example of an IntentService:

public class MyService extends IntentService {

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            // Do some work here, get Intent extras if any, etc.
            // ...
            // Once this method ends, the IntentService will stop itself.
        }
    }   
}

More info on how to create an IntentService can be found here.

That can handle your asynchronous operations. And if you need any feedback, which will "break" the async part of the requirement, you could use a LocalBroadcastManager or as you said, you could bind to this Service. And then again, it depends on what you're trying to do.

From the docs, you have two types of services.

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.

Reminder: You can start a Service through startService() to make it run "indefinitely" and bind to it by calling onBind() later.

Intent it = new Intent(this, MyService.class);
startService(it); // Start the service.
bindService(it, this, 0); // Bind to it.

If you want to simply run this service for as long as your Activity is running, you could just call onBind().

Intent it = new Intent(this, MyService.class);
bindService(it, this, 0); // This will create the service and bind to it.

More info on "default" Service, how to use it and implement it can be found here.

Just choose what works best for your use case, and you're good to go.

like image 157
Mauker Avatar answered Sep 29 '22 22:09

Mauker


The point is, you're not supposed to call both startService() and bindService(). If you want to bind to a service, call bindService(). When the service is connected, your implementation of ServiceConnection.onServiceConnected() is called, giving you an IBinder to the Service. Typically, a bound service is used as the server part of an internal client-server interface. You bind to the service, get back an IBinder that gives you a handle to the Service object itself, and then use the Service handle to pass data or call methods in the Service.

Bound services are almost always used to connect between processes (IPC).

like image 29
Joe Malin Avatar answered Sep 29 '22 22:09

Joe Malin