Services can be used by any application component that “hangs around” for a reasonable period of time. This includes activities, content providers, and other services. Notably, it does not include pure intent receivers (i.e., intent receivers that are not part of an activity), since those will get garbage collected immediately after each instance processes one incoming Intent.

To use a service, you need to get an instance of the AIDL interface for the service, then call methods on that interface as if it were a local object. When done, you can release the interface, indicating you no longer need the service.

In this chapter, we will look at the client side of the Service/WeatherPlus sample application. The WeatherPlus activity looks an awful lot like the original Weather application — just a Web page showing a weather forecast as you can see in Figure 31-1.

Figure 31-1. The WeatherPlus service client

The difference is that, as the emulator “moves”, the weather forecast changes, based on updates provided by the service.

Bound for Success

To use a service, you first need to create an instance of your own ServiceConnection class. ServiceConnection, as the name suggests, represents your connection to the service for the purposes of making IPC calls. For example, here is the ServiceConnection from the WeatherPlus class in the WeatherPlus project:

private ServiceConnection svcConn = new ServiceConnection() {

 public void onServiceConnected(ComponentName className,

  IBinder binder) {

  service = IWeather.Stub.asInterface(binder);

  browser.postDelayed(new Runnable() {

   public void run() {

    updateForecast();

   }

  }, 1000);

 }

 public void onServiceDisconnected(ComponentName className) {

  service = null;

 }

};

Your ServiceConnection subclass needs to implement two methods:

1. onServiceConnected(), which is called once your activity is bound to the service

2. onServiceDisconnected(), which is called if your connection ends normally, such as you unbinding your activity from the service

Each of those methods receives a ComponentName, which simply identifies the service you connected to. More importantly, onServiceConnected() receives an IBinder instance, which is your gateway to the IPC interface. You will want to convert the IBinder into an instance of your AIDL interface class, so you can use IPC as if you were calling regular methods on a regular Java class (IWeather.Stub.asInterface(binder)).

To actually hook your activity to the service, call bindService() on the activity:

bindService(serviceIntent, svcConn, BIND_AUTO_CREATE);

The bindService() method takes three parameters:

1. An Intent representing the service you wish to invoke — for your own service, it’s easiest to use an intent referencing the service class directly (new Intent(this, WeatherPlusService.class))

2. Your ServiceConnection instance

3. A set of flags — most times, you will want to pass in BIND_AUTO_CREATE, which will start up the service if it is not already running

After your bindService() call, your onServiceConnected() callback in the ServiceConnection will eventually be invoked, at which time your connection is ready for use.

Request for Service

Once your service interface object is ready (IWeather.Stub.asInterface(binder)), you can start calling methods on it as you need to. In fact, if you disabled some widgets awaiting the connection, now is a fine time to re-enable them.

However, you will want to trap two exceptions. One is DeadObjectException — if this is raised, your service connection terminated unexpectedly. In this case, you should unwind your use of the service, perhaps by calling onServiceDisconnected() manually, as shown previously. The other is RemoteException, which is a more general-purpose exception indicating a cross-process communications problem. Again, you should probably cease your use of the service.

Prometheus Unbound

When you are done with the IPC interface, call unbindService(), passing in the ServiceConnection. Eventually, your connection’s onServiceDisconnected() callback will be invoked, at which point you should null out your interface object, disable relevant widgets, or otherwise flag yourself as no longer being able to use the service.

For example, in the WeatherPlus implementation of onServiceDisconnected() shown previously, we null out the IWeather service object.

You can always reconnect to the service, via bindService(), if you need to use it again.

Manual Transmission

In addition to binding to the service for the purposes of IPC, you can manually start and stop the service. This is particularly useful in cases where you want the service to keep running independently of your activities — otherwise, once you unbind the service, your service could well be closed down.

To start a service, simply call startService(), providing two parameters:

Вы читаете Beginning Android
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату