1 使用AIDL(AndRoid接口描述语言)设计和使用远程接口
1.1 使用AIDL实现IPC
1.1.1 创建一个AIDL文件
1.1.2 实现接口
1.1.3 向客户端公开接口
1.1.4 使用parcelables进行参数的值传递
1.2 调用一个IPC方法
使用AIDL(AndRoid接口描述语言)设计和使用远程接口
Since each application runs in its own process, and you can write a service that runs in a different process from your Application's UI, sometimes you need to pass objects between processes. On the Android platform, one process can not normally access the memory of another process. So to talk, they need to decompose their objects into primitives that the operating system can understand, and "marshall" the object across that boundary for you.
通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的 service。在AndRoid平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。
The code to do that marshalling is tedious to write, so we provide the AIDL tool to do it for you.
编写这种伪装代码相当的枯燥乏味,好在我们提供了AIDL工具可以来做这件事。
AIDL (Android Interface Definition Language) is an IDL language used to generate code that enables two processes on an Android device to talk using interprocess communication (IPC). If you have code in one process (for example, in an Activity) that needs to call methods on an object in another process (for example, a Service), you would use AIDL to generate code to marshall the parameters.
AIDL(AndRoid接口描述语言)是一个 IDL语言,它可以生成一段代码,可以使在一个AndRoid设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个 Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用 AIDL来生成这样的代码来伪装传递各种参数。
The AIDL IPC mechanism is interface-based, similar to COM or Corba, but lighter weight. It uses a proxy class to pass values between the client and the implementation.
AIDL IPC的机制是基于接口的,和COM或Corba类似,但它是轻量级的。它使用代理类在客户端和实现层间传递值。
This page includes the following main topics:
本页包含以下主题:
Implementing IPC Using AIDL
Calling an .aidl (IPC) Class
使用AIDL实现IPC
调用一个AIDL(IPC)类
使用AIDL实现IPC
Follow these steps to implement an IPC service using AIDL.
使用AIDL实现一个IPC有下列步骤:
1.Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client.
1、创建你的AIDL文件 - 这个文件定义一个接口(YourInterface.aidl),该接口定义了可供客户端访问的方法和属性。
2.Add the .aidl file to your makefile - (the Eclipse plugin manages this for you). Android includes the compiler, called AIDL, in the tools/ directory.
2、添加AIDL文件到你的makefile中-(Eclipse plugin可以帮你管理)。AndRoid包括编译器,AIDL调用,这些都能在tools/directory中找到。
3.Implement your interface methods - The AIDL compiler creates an interface in the Java programming language from your AIDL interface. This interface has an inner abstract class named Stub that inherits the interface (and implements a few additional methods necessary for the IPC call). You must create a class that extends YourInterface.Stub and implements the methods you declared in your .aidl file.
3、实现接口方法-AIDL编译器从你的AIDL接口中使用JAVA编程语言来创建一个接口。这个接口有一个名为Stub的内部抽象类,它继承接口(并实现供IPC调用的所必需的几个附加方法)。你必须创建一个类来实现该接口。
4.Expose your interface to clients - If you're writing a service, you should extend Service and override getBinder() to returning an instance of your class that implements your interface.
4、向客户端开放接口-如果你写个service,你应该扩展该Service并重载getBinder()方法来返回一个实现上述接口的类的实例。
[编辑] 创建一个AIDL文件
AIDL is a simple syntax that lets you declare an interface with one or more methods, that can take parameters and return values. These parameters and return values can be of any type, even other AIDL-generated interfaces. However, it is important to note that you must import all non-built-in types, even if they are defined in the same package as your interface. Here are the data types that AIDL can support:
AIDL 语法简单,你可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。这些参数和返回值可以是任何类型,甚至是其他的AIDL 生成的接口。然而,值得重视的是你必须导入所有的non-bult-in类型,即使他们已经作为接口在其他包里定义了。下面是些AIDL支持的数据类型:
Primitive Java programming language types (int, boolean, etc) — No import statement is needed.
简单Java编程语言类型(int,boolean等) -不需要import声明。
One of the following classes (no import statements needed):
下面类之一(不需要import声明)
Java 代码
1. .String
2. .List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces
3. and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class
4. that the other side will receive will always be an ArrayList, although the method will be generated to use the
5. List interface.
6. .List - List 中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。List可以作为泛型类来灵活使用(比如
7. List<String>)。 而实际的接受方的类则总是ArrayList,尽管该方法将被生成来使用List接口。
8. .Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces
9. and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class
10. that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface.
11. .Map - Map 中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。
12. 而实际的接受方的类则总是 HashMap,尽管该方法将被生成去使用Map接口。
13. .CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.
14. .CharSequence - CharSequence 的作用是可以被TextView和其他Widget对象使用。
.String
.List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces
and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class
that the other side will receive will always be an ArrayList, although the method will be generated to use the
List interface.
.List - List中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。List可以作为泛型类来灵活使用(比如
List<String>)。而实际的接受方的类则总是ArrayList,尽管该方法将被生成来使用List接口。
.Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces
and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class
that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface.
.Map - Map中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。
而实际的接受方的类则总是HashMap,尽管该方法将被生成去使用Map接口。
.CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.
.CharSequence - CharSequence的作用是可以被TextView和其他Widget对象使用。
Other AIDL-generated interfaces, which are always passed by reference. An import statement is always needed for these. Custom classes that implement the Parcelable protocol and are passed by value. An import statement is always needed for these.
其他的AIDL生成接口通过引用方式进行传递。所以import声明是必须的。封装协议实现的自定义的类是值传递的方式。所以import声明也是必须的。
Here is the basic AIDL syntax:
下面是基本的AIDL语法:
Java 代码
1. // My AIDL file, named SomeClass.aidl
2. // Note that standard comment syntax is respected.
3. // Comments before the import or package statements are not bubbled up
4. // to the generated interface, but comments above interface/method/field
5. // declarations are added to the generated interface.
6. // Include your fully-qualified package statement.
7. package com.google.android.sample;
8. // See the list above for which classes need
9. // import statements (hint--most of them)
10. import com.google.android.sample.IAtmService;
11. // Declare the interface.
12. interface IBankAccountService {
13. // Methods can take 0 or more parameters, and
14. // return a value or void.
15. int getAccountBalance();
16. void setOwnerNames(in List<String> names);
17. // Methods can even take other AIDL-defined parameters.
18. BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);
19. // All non-Java primitive parameters (e.g., int, bool, etc) require
20. // a directional tag indicating which way the data will go. Available
21. // values are in, out, inout. (Primitives are in by default, and cannot be otherwise).
22. // Limit the direction to what is truly needed, because marshalling parameters
23. // is expensive.
24. int getCustomerList(in String branch, out String[] customerList);
25. }
// My AIDL file, named SomeClass.aidl
// Note that standard comment syntax is respected.
// Comments before the import or package statements are not bubbled up
// to the generated interface, but comments above interface/method/field
// declarations are added to the generated interface.
// Include your fully-qualified package statement.
package com.google.android.sample;
// See the list above for which classes need
// import statements (hint--most of them)
import com.google.android.sample.IAtmService;
// Declare the interface.
interface IBankAccountService {
// Methods can take 0 or more parameters, and
// return a value or void.
int getAccountBalance();
void setOwnerNames(in List<String> names);
// Methods can even take other AIDL-defined parameters.
BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);
// All non-Java primitive parameters (e.g., int, bool, etc) require
// a directional tag indicating which way the data will go. Available
// values are in, out, inout. (Primitives are in by default, and cannot be otherwise).
// Limit the direction to what is truly needed, because marshalling parameters
// is expensive.
int getCustomerList(in String branch, out String[] customerList);
}
实现接口
AIDL generates an interface file for you with the same name as your .aidl file. If you are using the Eclipse plugin, AIDL will automatically be run as part of the build process (you don't need to run AIDL first and then build your project). If you are not using the plugin, you should run AIDL first.
AIDL生成一个接口文件,文件名和你的AIDL文件名一致。如果你使用的是Eclipse插件,AIDL会作为build过程的一部分自动运行 (你不需要首先运行ADIL然后再去创建你的项目)。否则的话,你需要首先运行AIDL。
The generated interface includes an abstract inner class named Stub that declares all the methods that you declared in your .aidl file. Stub also defines a few helper methods, most notably asInterface(), which takes an IBinder (passed to a client's onServiceConnected() implementation when applicationContext.bindService() succeeds), and returns an instance of the interface used to call the IPC methods. See the section Calling an IPC Method for more details on how to make this cast.
生成的接口包括一个名为Stub的内部抽象类,该类声明了你在aidl文件中声明的所有方法。Stub也定义几个有用的方法,最特别的是 asInterface(),它执行一个IBinder(在 applicationContext.bindService()执行成功后传给客户端onServiceConnected()方法),并返回一个用来调用IPC方法的接口实例。更多细节请查看章节调用IPC方法。
To implement your interface, extend YourInterface.Stub, and implement the methods. (You can create the .aidl file and implement the stub methods without building between--the Android build process will process .aidl files before .java files.)
实现接口,扩展YourInterface.Stub,并实现方法成员。(你可以创建一个aidl文件并实现stub方法而不用绑定 -AndRoid创建过程在java文件之前会处理aidl文件)。
Here is an example of implementing an interface called IRemoteService, which exposes a single method, getPid(), using an anonymous instance:
这里有个例子,它实现了一个调用IRemoteService的接口,并使用匿名实例公开一个简单的方法gerPid():
Java 代码
1. // No need to import IRemoteService if it's in the same project.
2. private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
3. public int getPid(){
4. return Process.myPid();
5. }
6. }
// No need to import IRemoteService if it's in the same project.
private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public int getPid(){
return Process.myPid();
}
}
A few rules about implementing your interface:
实现接口时有几个原则:
Java 代码
1. .No exceptions that you throw will be sent back to the caller.
2. . 抛出的异常不要返回给调用者。
3. .IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete,
4. you should not call it in the Activity/View thread, because it might hang the application (Android might display
5. an "Application is Not Responding" dialog). Try to call them in a separate thread.
6. .IPC 调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity/View线程中调用。
7. 因 为它会挂起应用程序(AndRoid可能会显示"应用程序没有响应"对话框)。试着在一个独立的线程中调用。
8. .Only methods are supported; you cannot declare static fields in an AIDL interface.
9. . 只有方法才获得支持;你不能在AIDL接口中声明静态属性。
.No exceptions that you throw will be sent back to the caller.
.抛出的异常不要返回给调用者。
.IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete,
you should not call it in the Activity/View thread, because it might hang the application (Android might display
an "Application is Not Responding" dialog). Try to call them in a separate thread.
.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity/View线程中调用。
因为它会挂起应用程序(AndRoid可能会显示"应用程序没有响应"对话框)。试着在一个独立的线程中调用。
.Only methods are supported; you cannot declare static fields in an AIDL interface.
.只有方法才获得支持;你不能在AIDL接口中声明静态属性。
向客户端公开接口
Now that you've got your interface implementation, you need to expose it to clients. This is known as "publishing your service." To publish a service, inherit Service and implement getBinder() to return an instance of the class that implements your interface. Here's a code snippet of a service that exposes the IRemoteService interface to clients
现在你已完成了接口的实现,你需要向客户端公开该实现。这就是我们所熟悉的"发布服务"。发布一个Service,然后继承 Service并实现getBinder()返回一个实现的类的实例。下面是个Service的代码片断,该Service向客户端公了 IRemoteService接口。
Java 代码
1. public class RemoteService extends Service {
2. ...
3. @Override
4. public IBinder getBinder() {
5. return mBinder;
6. }
7. /**
8. * The IRemoteInterface is defined through IDL
9. */
10. private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
11. public int getPid() {
12. return Process.myPid();
13. }
14. };
15. }
public class RemoteService extends Service {
...
@Override
public IBinder getBinder() {
return mBinder;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public int getPid() {
return Process.myPid();
}
};
}
使用parcelables进行参数的值传递
Java 代码
1. Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try: 警告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息:
2.
3. .aidl files that only declare parcelables don't need to go in the makefile
4. . 仅声明parcelables的.aidl文件不需要写进makefile
5. .aidl can only generate code for interfaces, not parcelables
6. .aidl 只能生成接口代码,而不是parcelables。
7.
8. This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files.
9.
10. 这是个众所周知的局限。Parcelables仍然可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行aidl工具。下面的步骤5说明为何Eclipse不该尝试编译这些aidl文件。
Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try: 警告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息:
.aidl files that only declare parcelables don't need to go in the makefile
.仅声明parcelables的.aidl文件不需要写进makefile
.aidl can only generate code for interfaces, not parcelables
.aidl只能生成接口代码,而不是parcelables。
This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files.
这是个众所周知的局限。 Parcelables仍然可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行aidl工具。下面的步骤5说明为何Eclipse不该尝试编译这些aidl文件。
If you have a class that you would like to send from one process to another through an AIDL interface, you can do that. You must ensure that the code for your class is available to the other side of the IPC. Generally, that means that you're talking to a service that you started.
如果你有类需要通过AIDL接口从一个进程发送到另一个,你必须确保类代码可以被IPC接收端所使用。通常这意味着一开始你就要和service 进行通讯。
There are five parts to making a class support the Parcelable protocol:
让类支持parcelable协议,有五点需要注意
1.Make your class implement the Parcelable interface.
1. 让类实现Parcelable接口。
2.Implement the method public void writeToParcel(Parcel out) that takes the current state of the object and writes it to a parcel.
2. 实现public void writeToParcel(Parcel out),该方法可以将当前对象的状态写入parcel.
3.Implement the method public void readFromParcel(Parcel in) that reads the value in a parcel into your object.
3. 实现public void readFromParcel(Parcel in),该方法可以在 parcel中读出值到对象中.
4.Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface.
4. 向类中添加一个静态成员,名为CREATOR。该对象实现了 Parcelable.Creator接口.
5.Last but not least, add an aidl file for your parcelable class so the AIDL tool can find it, but don't add it to your build. This file is used like a header file in C. You don't compile the aidl file for a parcelable just like you wouldn't normally compile a .h file.
5. 向parcelable类中添加一个.aidl文件,以便AIDl工具可以找到。但不要向build中添加该文件。该文件的用法类似于C中的头文件.你不需要为parcelable编译aidl文件,就像你不会编译个.h文件一样。
AIDL will use these methods and fields in the code it generates to marshall and unmarshall your objects.
AIDL将使用代码中生成的这些方法和成员来伪装或解读对象。
Here is an example of how the Rect class implements the Parcelable protocol.
下面的例子说明了Rect类如何实现了Parcelable协议.
Java 代码
1. import android.os.Parcel;
2. import android.os.Parcelable;
3. public final class Rect implements Parcelable {
4. public int left;
5. public int top;
6. public int right;
7. public int bottom;
8. public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> {
9. public Rect createFromParcel(Parcel in) {
10. return new Rect(in);
11. }
12. public Rect[] newArray(int size) {
13. return new Rect[size];
14. }
15. };
16. public Rect() { }
17. private Rect(Parcel in) {
18. readFromParcel(in);
19. }
20. public void writeToParcel(Parcel out) {
21. out.writeInt(left);
22. out.writeInt(top);
23. out.writeInt(right);
24. out.writeInt(bottom);
25. }
26. public void readFromParcel(Parcel in) {
27. left = in.readInt();
28. top = in.readInt();
29. right = in.readInt();
30. bottom = in.readInt();
31. }
32. }
import android.os.Parcel;
import android.os.Parcelable;
public final class Rect implements Parcelable {
public int left;
public int top;
public int right;
public int bottom;
public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> {
public Rect createFromParcel(Parcel in) {
return new Rect(in);
}
public Rect[] newArray(int size) {
return new Rect[size];
}
};
public Rect() { }
private Rect(Parcel in) {
readFromParcel(in);
}
public void writeToParcel(Parcel out) {
out.writeInt(left);
out.writeInt(top);
out.writeInt(right);
out.writeInt(bottom);
}
public void readFromParcel(Parcel in) {
left = in.readInt();
top = in.readInt();
right = in.readInt();
bottom = in.readInt();
}
}
Here is Rect.aidl for this example
示例的Rect.aidl
1. package android.graphics;
2. // Declare Rect so AIDL can find it and knows that it implements
3. // the parcelable protocol.
4. parcelable Rect;
package android.graphics;
// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;
The marshalling in the Rect class is pretty simple. Take a look at the other methods on Parcel to see the other kinds of values you can write to a Parcel.
Rect类中的伪装是相当简单的。仔细看看Parcel中的其他方法,你会看到其他各种值你都可以写进Parcel.
Java 代码
1. Warning: Don't forget the security implications of receiving data from other processes. In this case, the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do. See Security and Permissions in Android for more on how to keep your application secure from malware.
2.
3. 警告:不要忽视从其他进程接收数据时的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
Warning: Don't forget the security implications of receiving data from other processes. In this case, the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do. See Security and Permissions in Android for more on how to keep your application secure from malware.
警告:不要忽视从其他进程接收数据时的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
调用一个IPC方法
Here are the steps a calling class should make to call your remote interface:
调用类调用远程接口的步骤:
1.Declare a variable of the interface type that your .aidl file defined.
Java 代码
1.声明一个接口类型的变量,该接口类型在.aidl文件中定义。
2.Implement ServiceConnection.
2.实现ServiceConnection。
3.Call ApplicationContext.bindService(), passing in your ServiceConnection implementation.
3.调用ApplicationContext.bindService(),并在 ServiceConnection实现中进行传递.
4.In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service).
Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
4.在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用
YourInterfaceName.Stub.asInterface((IBinder)service) 将参数转换为YourInterface类型。
5.Call the methods that you defined on your interface. You should always trap DeadObjectException exceptions, which are
thrown when the connection has broken; this will be the only exception thrown by remote methods.
5.调用接口中定义的方法。 你总会捕捉到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
6.To disconnect, call ApplicationContext.unbindService() with the instance of your interface.
6. 断开连接,调用接口实例中的 ApplicationContext.unbindService()
A few comments on calling an IPC service:
调用IPC服务需要注意几点:
Java 代码
1. .Objects are reference counted across processes.
2.
3. .You can send anonymous objects as method arguments.
4. . 匿名对象可以通过方法参数发送。
.Objects are reference counted across processes.
.You can send anonymous objects as method arguments.
.匿名对象可以通过方法参数发送。
Here is some sample code demonstrating calling an AIDL-created service, taken from the Remote Activity sample in the ApiDemos project.
下面的代码展示了在ApiDemos项目从远程Activity例子中调用AIDL创建Service的过程。
Java 代码
1. public class RemoteServiceBinding extends Activity{
2. IRemoteService mService = null;
3. Button mKillButton;
4. private boolean mIsBound;
5. @Override
6. protected void onCreate(Bundle icicle) {
7. super.onCreate(icicle);
8. setContentView(R.layout.remote_service_binding);
9. // Watch for button clicks.
10. Button button = (Button)findViewById(R.id.bind);
11. button.setOnClickListener(mBindListener);
12. button = (Button)findViewById(R.id.unbind);
13. button.setOnClickListener(mUnbindListener);
14. mKillButton = (Button)findViewById(R.id.kill);
15. mKillButton.setOnClickListener(mKillListener);
16. mKillButton.setEnabled(false);
17. }
18. private ServiceConnection mConnection = new ServiceConnection() {
19. public void onServiceConnected(ComponentName className, IBinder service) {
20. // This is called when the connection with the service has been
21. // established, giving us the service object we can use to
22. // interact with the service. We are communicating with our
23. // service through an IDL interface, so get a client-side
24. // representation of that from the raw service object.
25. mService = IRemoteService.Stub.asInterface((IBinder)service);
26. mKillButton.setEnabled(true);
27. // As part of the sample, tell the user what happened.
28. NotificationManager nm = (NotificationManager)
29. getSystemService(NOTIFICATION_SERVICE);
30. nm.notifyWithText(R.string.remote_service_connected,
31. getText(R.string.remote_service_connected),
32. NotificationManager.LENGTH_SHORT,
33. null);
34. }
35. public void onServiceDisconnected(ComponentName className) {
36. // This is called when the connection with the service has been
37. // unexpectedly disconnected -- that is, its process crashed.
38. mService = null;
39. mKillButton.setEnabled(false);
40. // As part of the sample, tell the user what happened.
41. NotificationManager nm = (NotificationManager)
42. getSystemService(NOTIFICATION_SERVICE);
43. nm.notifyWithText(R.string.remote_service_disconnected,
44. getText(R.string.remote_service_disconnected),
45. NotificationManager.LENGTH_SHORT,
46. null);
47. }
48. };
49. private OnClickListener mBindListener = new OnClickListener() {
50. public void onClick(View v) {
51. // Establish a connection with the service, by its class name.
52. bindService(new Intent(RemoteServiceBinding.this,
53. RemoteService.class),
54. null, mConnection, Context.BIND_AUTO_CREATE);
55. mIsBound = true;
56. }
57. };
58. private OnClickListener mUnbindListener = new OnClickListener() {
59. public void onClick(View v) {
60. if (mIsBound) {
61. // Detach our existing connection.
62. unbindService(mConnection);
63. mKillButton.setEnabled(false);
64. mIsBound = false;
65. }
66. }
67. };
68. private OnClickListener mKillListener = new OnClickListener() {
69. public void onClick(View v) {
70. // To kill the process hosting our service, we need to know its
71. // PID. Conveniently our service has a call that will return
72. // to us that information.
73. if (mService != null) {
74. int pid = -1;
75. try {
76. pid = mService.getPid();
77. } catch (DeadObjectException ex) {
78. // Recover gracefully from the process hosting the
79. // server dying.
80. // Just for purposes of the sample, put up a notification.
81. NotificationManager nm = (NotificationManager)
82. getSystemService(NOTIFICATION_SERVICE);
83. nm.notifyWithText(R.string.remote_call_failed,
84. getText(R.string.remote_call_failed),
85. NotificationManager.LENGTH_SHORT,
86. null);
87. }
88. if (pid > 0) {
89. // Go away!
90. Process.killProcess(pid);
91. }
92. }
93. }
94. };
95. }
1.1 使用AIDL实现IPC
1.1.1 创建一个AIDL文件
1.1.2 实现接口
1.1.3 向客户端公开接口
1.1.4 使用parcelables进行参数的值传递
1.2 调用一个IPC方法
使用AIDL(AndRoid接口描述语言)设计和使用远程接口
Since each application runs in its own process, and you can write a service that runs in a different process from your Application's UI, sometimes you need to pass objects between processes. On the Android platform, one process can not normally access the memory of another process. So to talk, they need to decompose their objects into primitives that the operating system can understand, and "marshall" the object across that boundary for you.
通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的 service。在AndRoid平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。
The code to do that marshalling is tedious to write, so we provide the AIDL tool to do it for you.
编写这种伪装代码相当的枯燥乏味,好在我们提供了AIDL工具可以来做这件事。
AIDL (Android Interface Definition Language) is an IDL language used to generate code that enables two processes on an Android device to talk using interprocess communication (IPC). If you have code in one process (for example, in an Activity) that needs to call methods on an object in another process (for example, a Service), you would use AIDL to generate code to marshall the parameters.
AIDL(AndRoid接口描述语言)是一个 IDL语言,它可以生成一段代码,可以使在一个AndRoid设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个 Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用 AIDL来生成这样的代码来伪装传递各种参数。
The AIDL IPC mechanism is interface-based, similar to COM or Corba, but lighter weight. It uses a proxy class to pass values between the client and the implementation.
AIDL IPC的机制是基于接口的,和COM或Corba类似,但它是轻量级的。它使用代理类在客户端和实现层间传递值。
This page includes the following main topics:
本页包含以下主题:
Implementing IPC Using AIDL
Calling an .aidl (IPC) Class
使用AIDL实现IPC
调用一个AIDL(IPC)类
使用AIDL实现IPC
Follow these steps to implement an IPC service using AIDL.
使用AIDL实现一个IPC有下列步骤:
1.Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client.
1、创建你的AIDL文件 - 这个文件定义一个接口(YourInterface.aidl),该接口定义了可供客户端访问的方法和属性。
2.Add the .aidl file to your makefile - (the Eclipse plugin manages this for you). Android includes the compiler, called AIDL, in the tools/ directory.
2、添加AIDL文件到你的makefile中-(Eclipse plugin可以帮你管理)。AndRoid包括编译器,AIDL调用,这些都能在tools/directory中找到。
3.Implement your interface methods - The AIDL compiler creates an interface in the Java programming language from your AIDL interface. This interface has an inner abstract class named Stub that inherits the interface (and implements a few additional methods necessary for the IPC call). You must create a class that extends YourInterface.Stub and implements the methods you declared in your .aidl file.
3、实现接口方法-AIDL编译器从你的AIDL接口中使用JAVA编程语言来创建一个接口。这个接口有一个名为Stub的内部抽象类,它继承接口(并实现供IPC调用的所必需的几个附加方法)。你必须创建一个类来实现该接口。
4.Expose your interface to clients - If you're writing a service, you should extend Service and override getBinder() to returning an instance of your class that implements your interface.
4、向客户端开放接口-如果你写个service,你应该扩展该Service并重载getBinder()方法来返回一个实现上述接口的类的实例。
[编辑] 创建一个AIDL文件
AIDL is a simple syntax that lets you declare an interface with one or more methods, that can take parameters and return values. These parameters and return values can be of any type, even other AIDL-generated interfaces. However, it is important to note that you must import all non-built-in types, even if they are defined in the same package as your interface. Here are the data types that AIDL can support:
AIDL 语法简单,你可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。这些参数和返回值可以是任何类型,甚至是其他的AIDL 生成的接口。然而,值得重视的是你必须导入所有的non-bult-in类型,即使他们已经作为接口在其他包里定义了。下面是些AIDL支持的数据类型:
Primitive Java programming language types (int, boolean, etc) — No import statement is needed.
简单Java编程语言类型(int,boolean等) -不需要import声明。
One of the following classes (no import statements needed):
下面类之一(不需要import声明)
Java 代码
1. .String
2. .List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces
3. and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class
4. that the other side will receive will always be an ArrayList, although the method will be generated to use the
5. List interface.
6. .List - List 中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。List可以作为泛型类来灵活使用(比如
7. List<String>)。 而实际的接受方的类则总是ArrayList,尽管该方法将被生成来使用List接口。
8. .Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces
9. and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class
10. that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface.
11. .Map - Map 中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。
12. 而实际的接受方的类则总是 HashMap,尽管该方法将被生成去使用Map接口。
13. .CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.
14. .CharSequence - CharSequence 的作用是可以被TextView和其他Widget对象使用。
.String
.List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces
and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class
that the other side will receive will always be an ArrayList, although the method will be generated to use the
List interface.
.List - List中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。List可以作为泛型类来灵活使用(比如
List<String>)。而实际的接受方的类则总是ArrayList,尽管该方法将被生成来使用List接口。
.Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces
and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class
that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface.
.Map - Map中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。
而实际的接受方的类则总是HashMap,尽管该方法将被生成去使用Map接口。
.CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.
.CharSequence - CharSequence的作用是可以被TextView和其他Widget对象使用。
Other AIDL-generated interfaces, which are always passed by reference. An import statement is always needed for these. Custom classes that implement the Parcelable protocol and are passed by value. An import statement is always needed for these.
其他的AIDL生成接口通过引用方式进行传递。所以import声明是必须的。封装协议实现的自定义的类是值传递的方式。所以import声明也是必须的。
Here is the basic AIDL syntax:
下面是基本的AIDL语法:
Java 代码
1. // My AIDL file, named SomeClass.aidl
2. // Note that standard comment syntax is respected.
3. // Comments before the import or package statements are not bubbled up
4. // to the generated interface, but comments above interface/method/field
5. // declarations are added to the generated interface.
6. // Include your fully-qualified package statement.
7. package com.google.android.sample;
8. // See the list above for which classes need
9. // import statements (hint--most of them)
10. import com.google.android.sample.IAtmService;
11. // Declare the interface.
12. interface IBankAccountService {
13. // Methods can take 0 or more parameters, and
14. // return a value or void.
15. int getAccountBalance();
16. void setOwnerNames(in List<String> names);
17. // Methods can even take other AIDL-defined parameters.
18. BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);
19. // All non-Java primitive parameters (e.g., int, bool, etc) require
20. // a directional tag indicating which way the data will go. Available
21. // values are in, out, inout. (Primitives are in by default, and cannot be otherwise).
22. // Limit the direction to what is truly needed, because marshalling parameters
23. // is expensive.
24. int getCustomerList(in String branch, out String[] customerList);
25. }
// My AIDL file, named SomeClass.aidl
// Note that standard comment syntax is respected.
// Comments before the import or package statements are not bubbled up
// to the generated interface, but comments above interface/method/field
// declarations are added to the generated interface.
// Include your fully-qualified package statement.
package com.google.android.sample;
// See the list above for which classes need
// import statements (hint--most of them)
import com.google.android.sample.IAtmService;
// Declare the interface.
interface IBankAccountService {
// Methods can take 0 or more parameters, and
// return a value or void.
int getAccountBalance();
void setOwnerNames(in List<String> names);
// Methods can even take other AIDL-defined parameters.
BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);
// All non-Java primitive parameters (e.g., int, bool, etc) require
// a directional tag indicating which way the data will go. Available
// values are in, out, inout. (Primitives are in by default, and cannot be otherwise).
// Limit the direction to what is truly needed, because marshalling parameters
// is expensive.
int getCustomerList(in String branch, out String[] customerList);
}
实现接口
AIDL generates an interface file for you with the same name as your .aidl file. If you are using the Eclipse plugin, AIDL will automatically be run as part of the build process (you don't need to run AIDL first and then build your project). If you are not using the plugin, you should run AIDL first.
AIDL生成一个接口文件,文件名和你的AIDL文件名一致。如果你使用的是Eclipse插件,AIDL会作为build过程的一部分自动运行 (你不需要首先运行ADIL然后再去创建你的项目)。否则的话,你需要首先运行AIDL。
The generated interface includes an abstract inner class named Stub that declares all the methods that you declared in your .aidl file. Stub also defines a few helper methods, most notably asInterface(), which takes an IBinder (passed to a client's onServiceConnected() implementation when applicationContext.bindService() succeeds), and returns an instance of the interface used to call the IPC methods. See the section Calling an IPC Method for more details on how to make this cast.
生成的接口包括一个名为Stub的内部抽象类,该类声明了你在aidl文件中声明的所有方法。Stub也定义几个有用的方法,最特别的是 asInterface(),它执行一个IBinder(在 applicationContext.bindService()执行成功后传给客户端onServiceConnected()方法),并返回一个用来调用IPC方法的接口实例。更多细节请查看章节调用IPC方法。
To implement your interface, extend YourInterface.Stub, and implement the methods. (You can create the .aidl file and implement the stub methods without building between--the Android build process will process .aidl files before .java files.)
实现接口,扩展YourInterface.Stub,并实现方法成员。(你可以创建一个aidl文件并实现stub方法而不用绑定 -AndRoid创建过程在java文件之前会处理aidl文件)。
Here is an example of implementing an interface called IRemoteService, which exposes a single method, getPid(), using an anonymous instance:
这里有个例子,它实现了一个调用IRemoteService的接口,并使用匿名实例公开一个简单的方法gerPid():
Java 代码
1. // No need to import IRemoteService if it's in the same project.
2. private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
3. public int getPid(){
4. return Process.myPid();
5. }
6. }
// No need to import IRemoteService if it's in the same project.
private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public int getPid(){
return Process.myPid();
}
}
A few rules about implementing your interface:
实现接口时有几个原则:
Java 代码
1. .No exceptions that you throw will be sent back to the caller.
2. . 抛出的异常不要返回给调用者。
3. .IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete,
4. you should not call it in the Activity/View thread, because it might hang the application (Android might display
5. an "Application is Not Responding" dialog). Try to call them in a separate thread.
6. .IPC 调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity/View线程中调用。
7. 因 为它会挂起应用程序(AndRoid可能会显示"应用程序没有响应"对话框)。试着在一个独立的线程中调用。
8. .Only methods are supported; you cannot declare static fields in an AIDL interface.
9. . 只有方法才获得支持;你不能在AIDL接口中声明静态属性。
.No exceptions that you throw will be sent back to the caller.
.抛出的异常不要返回给调用者。
.IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete,
you should not call it in the Activity/View thread, because it might hang the application (Android might display
an "Application is Not Responding" dialog). Try to call them in a separate thread.
.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity/View线程中调用。
因为它会挂起应用程序(AndRoid可能会显示"应用程序没有响应"对话框)。试着在一个独立的线程中调用。
.Only methods are supported; you cannot declare static fields in an AIDL interface.
.只有方法才获得支持;你不能在AIDL接口中声明静态属性。
向客户端公开接口
Now that you've got your interface implementation, you need to expose it to clients. This is known as "publishing your service." To publish a service, inherit Service and implement getBinder() to return an instance of the class that implements your interface. Here's a code snippet of a service that exposes the IRemoteService interface to clients
现在你已完成了接口的实现,你需要向客户端公开该实现。这就是我们所熟悉的"发布服务"。发布一个Service,然后继承 Service并实现getBinder()返回一个实现的类的实例。下面是个Service的代码片断,该Service向客户端公了 IRemoteService接口。
Java 代码
1. public class RemoteService extends Service {
2. ...
3. @Override
4. public IBinder getBinder() {
5. return mBinder;
6. }
7. /**
8. * The IRemoteInterface is defined through IDL
9. */
10. private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
11. public int getPid() {
12. return Process.myPid();
13. }
14. };
15. }
public class RemoteService extends Service {
...
@Override
public IBinder getBinder() {
return mBinder;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public int getPid() {
return Process.myPid();
}
};
}
使用parcelables进行参数的值传递
Java 代码
1. Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try: 警告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息:
2.
3. .aidl files that only declare parcelables don't need to go in the makefile
4. . 仅声明parcelables的.aidl文件不需要写进makefile
5. .aidl can only generate code for interfaces, not parcelables
6. .aidl 只能生成接口代码,而不是parcelables。
7.
8. This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files.
9.
10. 这是个众所周知的局限。Parcelables仍然可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行aidl工具。下面的步骤5说明为何Eclipse不该尝试编译这些aidl文件。
Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try: 警告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息:
.aidl files that only declare parcelables don't need to go in the makefile
.仅声明parcelables的.aidl文件不需要写进makefile
.aidl can only generate code for interfaces, not parcelables
.aidl只能生成接口代码,而不是parcelables。
This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files.
这是个众所周知的局限。 Parcelables仍然可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行aidl工具。下面的步骤5说明为何Eclipse不该尝试编译这些aidl文件。
If you have a class that you would like to send from one process to another through an AIDL interface, you can do that. You must ensure that the code for your class is available to the other side of the IPC. Generally, that means that you're talking to a service that you started.
如果你有类需要通过AIDL接口从一个进程发送到另一个,你必须确保类代码可以被IPC接收端所使用。通常这意味着一开始你就要和service 进行通讯。
There are five parts to making a class support the Parcelable protocol:
让类支持parcelable协议,有五点需要注意
1.Make your class implement the Parcelable interface.
1. 让类实现Parcelable接口。
2.Implement the method public void writeToParcel(Parcel out) that takes the current state of the object and writes it to a parcel.
2. 实现public void writeToParcel(Parcel out),该方法可以将当前对象的状态写入parcel.
3.Implement the method public void readFromParcel(Parcel in) that reads the value in a parcel into your object.
3. 实现public void readFromParcel(Parcel in),该方法可以在 parcel中读出值到对象中.
4.Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface.
4. 向类中添加一个静态成员,名为CREATOR。该对象实现了 Parcelable.Creator接口.
5.Last but not least, add an aidl file for your parcelable class so the AIDL tool can find it, but don't add it to your build. This file is used like a header file in C. You don't compile the aidl file for a parcelable just like you wouldn't normally compile a .h file.
5. 向parcelable类中添加一个.aidl文件,以便AIDl工具可以找到。但不要向build中添加该文件。该文件的用法类似于C中的头文件.你不需要为parcelable编译aidl文件,就像你不会编译个.h文件一样。
AIDL will use these methods and fields in the code it generates to marshall and unmarshall your objects.
AIDL将使用代码中生成的这些方法和成员来伪装或解读对象。
Here is an example of how the Rect class implements the Parcelable protocol.
下面的例子说明了Rect类如何实现了Parcelable协议.
Java 代码
1. import android.os.Parcel;
2. import android.os.Parcelable;
3. public final class Rect implements Parcelable {
4. public int left;
5. public int top;
6. public int right;
7. public int bottom;
8. public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> {
9. public Rect createFromParcel(Parcel in) {
10. return new Rect(in);
11. }
12. public Rect[] newArray(int size) {
13. return new Rect[size];
14. }
15. };
16. public Rect() { }
17. private Rect(Parcel in) {
18. readFromParcel(in);
19. }
20. public void writeToParcel(Parcel out) {
21. out.writeInt(left);
22. out.writeInt(top);
23. out.writeInt(right);
24. out.writeInt(bottom);
25. }
26. public void readFromParcel(Parcel in) {
27. left = in.readInt();
28. top = in.readInt();
29. right = in.readInt();
30. bottom = in.readInt();
31. }
32. }
import android.os.Parcel;
import android.os.Parcelable;
public final class Rect implements Parcelable {
public int left;
public int top;
public int right;
public int bottom;
public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> {
public Rect createFromParcel(Parcel in) {
return new Rect(in);
}
public Rect[] newArray(int size) {
return new Rect[size];
}
};
public Rect() { }
private Rect(Parcel in) {
readFromParcel(in);
}
public void writeToParcel(Parcel out) {
out.writeInt(left);
out.writeInt(top);
out.writeInt(right);
out.writeInt(bottom);
}
public void readFromParcel(Parcel in) {
left = in.readInt();
top = in.readInt();
right = in.readInt();
bottom = in.readInt();
}
}
Here is Rect.aidl for this example
示例的Rect.aidl
1. package android.graphics;
2. // Declare Rect so AIDL can find it and knows that it implements
3. // the parcelable protocol.
4. parcelable Rect;
package android.graphics;
// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;
The marshalling in the Rect class is pretty simple. Take a look at the other methods on Parcel to see the other kinds of values you can write to a Parcel.
Rect类中的伪装是相当简单的。仔细看看Parcel中的其他方法,你会看到其他各种值你都可以写进Parcel.
Java 代码
1. Warning: Don't forget the security implications of receiving data from other processes. In this case, the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do. See Security and Permissions in Android for more on how to keep your application secure from malware.
2.
3. 警告:不要忽视从其他进程接收数据时的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
Warning: Don't forget the security implications of receiving data from other processes. In this case, the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do. See Security and Permissions in Android for more on how to keep your application secure from malware.
警告:不要忽视从其他进程接收数据时的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
调用一个IPC方法
Here are the steps a calling class should make to call your remote interface:
调用类调用远程接口的步骤:
1.Declare a variable of the interface type that your .aidl file defined.
Java 代码
1.声明一个接口类型的变量,该接口类型在.aidl文件中定义。
2.Implement ServiceConnection.
2.实现ServiceConnection。
3.Call ApplicationContext.bindService(), passing in your ServiceConnection implementation.
3.调用ApplicationContext.bindService(),并在 ServiceConnection实现中进行传递.
4.In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service).
Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
4.在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用
YourInterfaceName.Stub.asInterface((IBinder)service) 将参数转换为YourInterface类型。
5.Call the methods that you defined on your interface. You should always trap DeadObjectException exceptions, which are
thrown when the connection has broken; this will be the only exception thrown by remote methods.
5.调用接口中定义的方法。 你总会捕捉到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
6.To disconnect, call ApplicationContext.unbindService() with the instance of your interface.
6. 断开连接,调用接口实例中的 ApplicationContext.unbindService()
A few comments on calling an IPC service:
调用IPC服务需要注意几点:
Java 代码
1. .Objects are reference counted across processes.
2.
3. .You can send anonymous objects as method arguments.
4. . 匿名对象可以通过方法参数发送。
.Objects are reference counted across processes.
.You can send anonymous objects as method arguments.
.匿名对象可以通过方法参数发送。
Here is some sample code demonstrating calling an AIDL-created service, taken from the Remote Activity sample in the ApiDemos project.
下面的代码展示了在ApiDemos项目从远程Activity例子中调用AIDL创建Service的过程。
Java 代码
1. public class RemoteServiceBinding extends Activity{
2. IRemoteService mService = null;
3. Button mKillButton;
4. private boolean mIsBound;
5. @Override
6. protected void onCreate(Bundle icicle) {
7. super.onCreate(icicle);
8. setContentView(R.layout.remote_service_binding);
9. // Watch for button clicks.
10. Button button = (Button)findViewById(R.id.bind);
11. button.setOnClickListener(mBindListener);
12. button = (Button)findViewById(R.id.unbind);
13. button.setOnClickListener(mUnbindListener);
14. mKillButton = (Button)findViewById(R.id.kill);
15. mKillButton.setOnClickListener(mKillListener);
16. mKillButton.setEnabled(false);
17. }
18. private ServiceConnection mConnection = new ServiceConnection() {
19. public void onServiceConnected(ComponentName className, IBinder service) {
20. // This is called when the connection with the service has been
21. // established, giving us the service object we can use to
22. // interact with the service. We are communicating with our
23. // service through an IDL interface, so get a client-side
24. // representation of that from the raw service object.
25. mService = IRemoteService.Stub.asInterface((IBinder)service);
26. mKillButton.setEnabled(true);
27. // As part of the sample, tell the user what happened.
28. NotificationManager nm = (NotificationManager)
29. getSystemService(NOTIFICATION_SERVICE);
30. nm.notifyWithText(R.string.remote_service_connected,
31. getText(R.string.remote_service_connected),
32. NotificationManager.LENGTH_SHORT,
33. null);
34. }
35. public void onServiceDisconnected(ComponentName className) {
36. // This is called when the connection with the service has been
37. // unexpectedly disconnected -- that is, its process crashed.
38. mService = null;
39. mKillButton.setEnabled(false);
40. // As part of the sample, tell the user what happened.
41. NotificationManager nm = (NotificationManager)
42. getSystemService(NOTIFICATION_SERVICE);
43. nm.notifyWithText(R.string.remote_service_disconnected,
44. getText(R.string.remote_service_disconnected),
45. NotificationManager.LENGTH_SHORT,
46. null);
47. }
48. };
49. private OnClickListener mBindListener = new OnClickListener() {
50. public void onClick(View v) {
51. // Establish a connection with the service, by its class name.
52. bindService(new Intent(RemoteServiceBinding.this,
53. RemoteService.class),
54. null, mConnection, Context.BIND_AUTO_CREATE);
55. mIsBound = true;
56. }
57. };
58. private OnClickListener mUnbindListener = new OnClickListener() {
59. public void onClick(View v) {
60. if (mIsBound) {
61. // Detach our existing connection.
62. unbindService(mConnection);
63. mKillButton.setEnabled(false);
64. mIsBound = false;
65. }
66. }
67. };
68. private OnClickListener mKillListener = new OnClickListener() {
69. public void onClick(View v) {
70. // To kill the process hosting our service, we need to know its
71. // PID. Conveniently our service has a call that will return
72. // to us that information.
73. if (mService != null) {
74. int pid = -1;
75. try {
76. pid = mService.getPid();
77. } catch (DeadObjectException ex) {
78. // Recover gracefully from the process hosting the
79. // server dying.
80. // Just for purposes of the sample, put up a notification.
81. NotificationManager nm = (NotificationManager)
82. getSystemService(NOTIFICATION_SERVICE);
83. nm.notifyWithText(R.string.remote_call_failed,
84. getText(R.string.remote_call_failed),
85. NotificationManager.LENGTH_SHORT,
86. null);
87. }
88. if (pid > 0) {
89. // Go away!
90. Process.killProcess(pid);
91. }
92. }
93. }
94. };
95. }
相关推荐
Android远程接口之AIDL——Parcelable、in、out、inout简例 Parcelable in out inout AIDL例子中体现使用方式 详细介绍: http://blog.csdn.net/yangzhaomuma/article/details/50576017
本文将围绕“android远程监控”这一主题,深入探讨相关的技术和实现细节。 首先,我们要理解远程监控的基本原理。远程监控是指通过网络连接,使一台设备(手机)能够获取并控制另一台设备(如PC)的状态或操作。在...
这个"Android远程视频监控程序源码"很可能包含了一个完整的解决方案,帮助开发者理解和实现远程视频流的实时传输、显示以及控制功能。下面我们将深入探讨相关的关键知识点。 1. **Android SDK与编程环境**:首先,...
Android远程Service** 远程Service是Android系统中实现不同应用程序间服务共享的一种机制。它允许一个应用启动另一个应用中的Service,进行跨进程通信。要创建一个远程Service,首先需要定义一个包含服务操作接口...
其中,Android Studio 中的一个重要功能是调用 Restful WCF 接口,用于与远程服务器进行通信和数据交换。 在 Android Studio 中调用 Restful WCF 接口需要使用 Java 的标准类 HttpURLConnection,该类继承自 ...
本教程将深入探讨如何在Android应用中调用远程HTTP接口并处理返回的JSON数据。 一、HTTP请求库的选择 在Android中,我们可以使用多种库来发送HTTP请求,如HttpURLConnection(原生API)、Volley、Retrofit、OkHttp...
AIDL设计远程接口.ppt,专业介绍AIDL的文档
本资源“安卓Android源码——在Android远程上传以及下载图片---XFire框架.zip”提供了一个基于XFire框架实现的解决方案。XFire是一款轻量级的Java Web服务库,它为Android开发者提供了方便快捷的方式来处理网络通信...
本资源提供的"Android远程视频传输样例源码"是一个很好的学习起点,它涵盖了Android视频传输的核心技术与实践。 首先,Android视频传输涉及的主要技术包括网络通信协议(如TCP/IP、HTTP或WebRTC)、数据编码解码...
在Android平台上进行远程图片的上传和下载是移动应用开发中常见的需求,特别是在社交、电商或者媒体分享类应用中。XFire框架是一个专为Android设计的轻量级网络库,可以帮助开发者轻松实现这些功能。本教程将详细...
在Android平台上实现手机远程监控,通常涉及到多个技术领域,包括网络通信、图像处理、设备权限管理等。这个项目"Android手机远程监控源码"可能是提供了一整套解决方案,让我们一起探讨其中可能涉及的关键知识点。 ...
在Android系统中,底层接口和驱动开发是至关重要的部分,它们构成了Android运行的基础。这篇文章将深入探讨这个领域,包括Android的内核层、硬件抽象层(HAL)、设备驱动以及系统服务等方面,帮助开发者理解Android...
在Android平台上实现远程控制空调的功能是一项技术性强且实用的...以上知识点构成了一个完整的“android远程控制空调”应用的基本框架。通过这些技术,用户可以随时随地调整家中空调的设置,享受到科技带来的舒适生活。
下面我们将深入探讨Android远程服务的相关知识点。 **一、Android服务基础** 在理解远程服务之前,我们首先需要了解Android服务的基本概念。服务(Service)是Android四大组件之一,它在后台执行任务,不与用户...
在Android开发中,连接远程数据库是一项常见的任务,它允许应用程序从服务器获取或存储数据,实现数据的同步。这里我们将深入探讨如何在Android中实现这一功能,以及涉及的相关知识点。 首先,我们要了解Android与...
在Android开发中,远程数据库操作是一项重要技能,它允许应用程序通过网络与远程服务器进行数据交互,从而实现数据的存储和检索。本项目是基于Android Studio的,提供了实现远程数据库操作的源码,以及一个简单的...
本项目源码以"Android 在Android远程上传以及下载图片---XFire框架.zip"为标题,旨在教授如何利用XFire框架来实现这一功能。XFire是一款轻量级的Java库,专门用于构建RESTful Web服务,它简化了HTTP通信,使Android...
本篇将通过"Android远程服务小demo"来深入理解Android中的接口定义语言(AIDL,Android Interface Definition Language)以及进程间通信(IPC,Inter-Process Communication)。 首先,我们要了解什么是AIDL。AIDL...
《Android远程服务机制剖析》这篇文章主要探讨了Android系统中如何通过远程服务机制实现不同进程间的通信,以便解决后台耗时任务跨进程共享的问题。在移动互联网应用迅速发展的背景下,深入理解Android远程服务机制...
### 在Android中访问WebService接口 #### 一、引言 随着移动互联网的发展,越来越多的应用程序需要与后端服务器进行交互来获取数据或提供服务。在Android应用开发中,访问WebService接口是一种常见的通信方式。...