via the gps LocationProvider, which will be discussed in Chapter 33.

The onDestroy() method is much simpler:

@Override

public void onDestroy() {

 super.onDestroy();

 myLocationManager.removeUpdates(onLocationChange);

}

Here, we just shut down the location-monitoring logic, in addition to chaining upward to the superclass for any Android internal bookkeeping that might be needed.

In addition to those lifecycle methods, though, your service also needs to implement onBind() . This method returns an IBinder, which is the linchpin behind the IPC mechanism. If you’re creating a service class while reading this chapter, just have this method return null for now, and we’ll fill in the full implementation in the next section.

When IPC Attacks!

Services will tend to offer inter-process communication (IPC) as a means of interacting with activities or other Android components. Each service declares what methods it is making available over IPC; those methods are then available for other components to call, with Android handling all the messy details involved with making method calls across component or process boundaries.

The core of this, from the standpoint of the developer, is expressed in AIDL: the Android Interface Description Language. If you have used IPC mechanisms like COM, CORBA, or the like, you will recognize the notion of IDL. AIDL describes the public IPC interface, and Android supplies tools to build the client and server side of that interface.

With that in mind, let’s take a look at AIDL and IPC.

Write the AIDL

IDLs are frequently written in a “language-neutral” syntax. AIDL, on the other hand, looks a lot like a Java interface. For example, here is the AIDL for the IWeather:

package com.commonsware.android.service;

// Declare the interface.

interface IWeather {

 String getForecastPage();

}

As with a Java interface, you declare a package at the top. As with a Java interface, the methods are wrapped in an interface declaration (interface IWeather { ... }). And, as with a Java interface, you list the methods you are making available.

The differences, though, are critical.

First, not every Java type can be used as a parameter. Your choices are:

• Primitive values (int, float, double, boolean, etc.)

• String and CharSequence

• List and Map (from java.util)

• Any other AIDL-defined interfaces

• Any Java classes that implement the Parcelable interface, which is Android’s flavor of serialization

In the case of the latter two categories, you need to include import statements referencing the names of the classes or interfaces that you are using (e.g., import com.commonsware.android.ISomething). This is true even if these classes are in your own package — you have to import them anyway.

Next, parameters can be classified as in, out, or inout. Values that are out or inout can be changed by the service and those changes will be propagated back to the client. Primitives (e.g., int) can only be in; we included in for the AIDL for enable() just for illustration purposes.

Also, you cannot throw any exceptions. You will need to catch all exceptions in your code, deal with them, and return failure indications some other way (e.g., error code return values).

Name your AIDL files with the .aidl extension and place them in the proper directory based on the package name.

When you build your project, either via an IDE or via Ant, the aidl utility from the Android SDK will translate your AIDL into a server stub and a client proxy.

Implement the Interface

Given the AIDL-created server stub, now you need to implement the service, either directly in the stub, or by routing the stub implementation to other methods you have already written.

The mechanics of this are fairly straightforward:

• Create a private instance of the AIDL-generated .Stub class (e.g., IWeather.Stub)

• Implement methods matching up with each of the methods you placed in the AIDL

• Return this private instance from your onBind() method in the Service subclass

For example, here is the IWeather.Stub instance:

private final IWeather.Stub binder = new IWeather.Stub() {

 public String getForecastPage() {

  return(getForecastPageImpl());

 }

};

In this case, the stub calls the corresponding method on the service itself. That method, which simply returns the cached most-recent weather forecast for the current location, is shown here:

synchronized private String getForecastPageImpl() {

 return(forecast);

}

Note that AIDL IPC calls are synchronous, and so the caller is blocked until the IPC method returns. Hence, your services need to be quick about their work.

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

0

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

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