• No results found

Android Interface Definition Language

Intents and Services

4.5 Communicating with the WeatherAlertService from other apps

4.5.1 Android Interface Definition Language

If you want to allow other developers to use your weather features, you need to give them information about the methods you provide, but you might not want to share your application’s source code. Android lets you specify your IPC features by using an interface definition language (IDL) to create AIDL files. These files generate a Java interface and an inner Stub class that you can use to create a remotely accessible object, and that your consumers can use to invoke your methods.

AIDL files allow you to define your package, imports, and methods with return types and parameters. Our weather AIDL, which we place in the same package as the .java files, is shown in the following listing.

package com.msi.manning.weather; interface IWeatherReporter {

Listing 4.7 IWeatherReporter.aidl remote IDL file

A warning about long-running services

Our sample application starts a Service and leaves it running in the background. Our service is designed to have a minimal footprint, but Android best practices discour- age long-running services. Services that run continually and constantly use the net- work or perform CPU-intensive tasks will eat up the device’s battery life and might slow down other operations. Even worse, because they run in the background, the user won’t know what applications are to blame for her device’s poor performance. The OS will eventually kill running services if it needs to acquire additional memory, but otherwise won’t interfere with poorly designed services. If your use case no longer requires the service, you should stop it. If you do require a long-running service, you might want to give the user the option of whether to use it.

String getWeatherFor(in String zip);

void addLocation(in String zip, in String city, in String region); }

You define the package and interface in AIDL as you would in a regular Java file. Simi- larly, if you require any imports, you’d list them above the interface declaration. When you define methods, you must specify a directional tag for all nonprimitive types. The possible directions are in, out, and inout. The platform uses this directional tag to generate the necessary code for marshaling and unmarshaling instances of your inter- face across IPC boundaries.

Our interface IWeatherReporter includes methods to look up the current weather from the service, or to add a new location to the service. Other developers could use these features to provide other front-end applications that use our back-end service.

Only certain types of data are allowed in AIDL, as shown in table 4.5. Types that require an import must always list that import, even if they’re in the same package as your .aidl file.

After you’ve defined your interface methods with return types and parameters, you then invoke the aidl tool included in your Android SDK installation to generate a Java interface that represents your AIDL specification. If you use the Eclipse plug-in, it’ll automatically invoke the aidl tool for you, placing the generated files in the appropri- ate package in your project’s gen folder.

The interface generated through AIDL includes an inner static abstract class named Stub that extends Binder and implements the outer class interface. This Stub class represents the local side of your remotable interface. Stub also includes an asInterface(IBinder binder) method that returns a remote version of your interface type. Callers can use this method to get a handle to the remote object and use it to invoke remote methods. The AIDL process generates a Proxy class (another inner class, this time inside Stub) that connects all these components and returns to callers from the asInterface method. Figure 4.6 depicts this IPC local/remote relationship. Table 4.5 Android IDL allowed types

Type Description Import

required

Java primitives boolean, byte, short, int, float, double, long, char. No

String java.lang.String. No

CharSequence java.lang.CharSequence. No

List Can be generic; all types used in collection must be allowed by IDL. Ultimately provided as an ArrayList.

No

Map Can be generic, all types used in collection must be one allowed by IDL. Ultimately provided as a HashMap.

No

Other AIDL interfaces Any other AIDL-generated interface type. Yes

Parcelable objects Objects that implement the Android Parcelable interface, described in section 4.5.2.

AIDL is handled synchronously through the transaction process, enabling the same semantics as if the method were local.

All the objects you pass in and out through the interface methods that you define using AIDL use the transact process. These objects must be Parcelable in order to be able to be placed inside a Parcel and moved across the local/remote process barrier in the Binder transaction methods.

The only time you need to worry about something being Parcelable is when you want to send a custom object through Android IPC. If you use only the default allow- able types in your interface definition files—primitives, String, CharSequence, List, and Map—AIDL automatically handles everything.

The Android documentation describes what methods you need to implement to create a Parcelable class. Remember to create a .aidl file for each Parcelable inter- face. These .aidl files are different from those you use to define Binder classes them- selves; these shouldn’t be generated from the aidl tool.

CAUTION When you’re considering creating your own Parcelable types, make sure you actually need them. Passing complex objects across the IPC boundary in an embedded environment is an expensive and tedious opera- tion; you should avoid doing it, if possible.