`
java-admin
  • 浏览: 1381922 次
  • 性别: Icon_minigender_1
  • 来自: 陕西.西安
社区版块
存档分类
最新评论

使用AIDL(Android接口描述语言)设计和使用远程接口

阅读更多

 

目录

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协议,有五点需要注意

Java代码 复制代码
  1. 1 .Make your  class  implement the Parcelable  interface .    
  2.   1 . 让类实现 Parcelable接口。   
  3.   2 .Implement the method  public   void  writeToParcel(Parcel out) that takes the current state of the object and writes it    
  4.   to a parcel.    
  5.   2 . 实 现 public   void  writeToParcel(Parcel out), 该方法可以将当前对象的状态写入parcel.   
  6.   3 .Implement the method  public   void  readFromParcel(Parcel in) that reads the value in a parcel into your object.    
  7.   3 . 实现 public   void  readFromParcel(Parcel in), 该方法可以在parcel中读出值到对象中.   
  8.   4 .Add a  static  field called CREATOR to your  class  which is an object implementing the Parcelable.Creator  interface .    
  9.   4 . 向类中添加一个静态成员,名为 CREATOR。该对象实现了Parcelable.Creator接口.   
  10.   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    
  11.   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    
  12.   normally compile a .h file.    
  13.   5 . 向 parcelable类中添加一个.aidl文件,以便AIDl工具可以找到。但不要向build中添加该文件。该文件的用法类似于C中的头文件.你不需 要为parcelable   
  14.     编译aidl文件,就像你不会编译个.h文件一样。  
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

Java代码 复制代码
  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. 1 . 声明一个接口类型的变量,该接口类型在.aidl文件中定义。   
  2.   2 .Implement ServiceConnection.    
  3.   2 . 实现 ServiceConnection。   
  4.   3 .Call ApplicationContext.bindService(), passing in your ServiceConnection implementation.    
  5.   3 . 调用 ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.    
  6.   4 .In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service).    
  7.    Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.    
  8.   4 . 在 ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的 Service). 调用   
  9.     YourInterfaceName.Stub.asInterface((IBinder)service) 将参数转换为YourInterface类型。   
  10.   5 .Call the methods that you defined on your  interface . You should always trap DeadObjectException exceptions, which are    
  11.    thrown when the connection has broken;  this  will be the only exception thrown by remote methods.    
  12.   5 . 调用接口中定义的方法。 你总会捕捉到 DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。   
  13.   6 .To disconnect, call ApplicationContext.unbindService() with the instance of your  interface .    
  14.   6 . 断开连接,调用接口实例中的 ApplicationContext.unbindService()  
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.     };   

在android中,进程通讯是通过aidl机制来完成的。aidl模型如下:

                |<--------------------aidl---------------------->|
 client端 -->proxy  ----------parcel数据包-------- stub<---server端
也就是说:proxy+parcel+stub构成了aidl.只不过,proxy运行在客户进程,而 stub运行在服务端进程。当你通过aidl去访问服务端时,客户端会阻塞在proxy,服务端处理完后,通知proxy返回。

补充1:
应 用程序获取相关服务的代码:
private AlarmManager getAlarmManager() {
        synchronized (sSync) {
            if (sAlarmManager == null) {
                IBinder b = ServiceManager.getService(ALARM_SERVICE);
                IAlarmManager service = IAlarmManager.Stub.asInterface(b);
                sAlarmManager = new AlarmManager(service);
            }
        }
        return sAlarmManager;
    }


补充2:
AIDL文件生成的java文件中的Stub 类。
public static abstract class Stub extends android.os.Binder implements
            android.net.softap.ISoftApManager
{
        private static final java.lang.String DESCRIPTOR = "android.net.softap.ISoftApManager";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an ISoftApManager interface, generating a
         * proxy if needed.
         */
        public static android.net.softap.ISoftApManager asInterface (
                android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = (android.os.IInterface) obj
                    .queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof android.net.softap.ISoftApManager))) {
                return ((android.net.softap.ISoftApManager) iin);
            }
            return new android.net.softap.ISoftApManager.Stub.Proxy(obj);
        }

        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data,
                android.os.Parcel reply, int flags)
                throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_getApEnabledState: {
                data.enforceInterface(DESCRIPTOR);
                int _result = this.getApEnabledState();
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
            case TRANSACTION_setApEnabled: {
                data.enforceInterface(DESCRIPTOR);
                boolean _arg0;
                _arg0 = (0 != data.readInt());
                boolean _result = this.setApEnabled(_arg0);
                reply.writeNoException();
                reply.writeInt(((_result) ? (1) : (0)));
                return true;
            }
            case TRANSACTION_setApSettings: {
                data.enforceInterface(DESCRIPTOR);
                android.net.softap.SoftApConfigure _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = android.net.softap.SoftApConfigure.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                boolean _result = this.setApSettings(_arg0);
                reply.writeNoException();
                reply.writeInt(((_result) ? (1) : (0)));
                return true;
            }
            case TRANSACTION_getApSettings: {
                data.enforceInterface(DESCRIPTOR);
                android.net.softap.SoftApConfigure _result = this
                        .getApSettings();
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result
                            .writeToParcel(
                                    reply,
                                    android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements android.net.softap.ISoftApManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }


            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            public int getApEnabledState() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
   

分享到:
评论

相关推荐

    Android AIDL使用详解

    在Android系统中,AIDL(Android Interface Definition Language)是一种接口定义语言,用于处理进程间通信(IPC, Inter-Process Communication)。当一个应用需要与另一个应用的组件进行交互,特别是跨越不同进程时...

    android aidl 不同进程间通信

    Aidl是一种接口定义语言,用于描述服务端公开的接口和方法。通过Aidl,客户端可以透明地调用服务端的方法,就像调用本地对象一样。Aidl编译后会生成Java代码,实现跨进程调用所需的代理类和服务端的Stub类。 **3. ...

    Android aidl 实现进程间通信

    首先,AIDL是一种简单的接口描述语言,它的主要作用是定义接口,使得Android系统可以自动生成对应的Java绑定类,以便于两个不同进程间的对象调用对方的方法。AIDL文件通常以`.aidl`为扩展名,其中包含了方法声明、...

    Android的IPC与AIDL

    使用AIDL可以定义一个接口文件(通常以.aidl为后缀),这个文件描述了远程接口的行为,包括参数类型和返回值类型。AIDL编译器会根据该文件生成相应的Java代码,使得进程间能够互相调用接口中的方法。 **2. AIDL的...

    android进程通信之使用AIDL

    AIDL本质上是一种接口定义语言,用于描述服务提供的方法和数据类型。当一个应用需要与另一个应用的远程服务进行交互时,AIDL便发挥作用。通过编写AIDL文件,系统会自动生成相应的Java接口和Stub类,这些类帮助我们...

    安卓开发 AIDL学习demo android studio

    1. **AIDL定义**: AIDL 是一种简单的接口描述语言,类似于Java,但主要用于定义跨进程调用的方法签名。它允许你在服务中定义一套接口,其他应用可以使用这些接口来与服务进行通信。 2. **进程间通信(IPC)**: 在...

    Aidl服务详细介绍,包括使用方法和分析。

    AIDL是Android系统为了实现跨进程通信而设计的一种接口定义语言。它允许开发者定义接口,使得服务端(服务运行的进程)和客户端(调用服务的进程)可以互相调用方法,即使它们位于不同的进程中。AIDL生成对应的Java...

    安卓Android源码——AidlDemo(简单aidl的例子).zip

    1. **基本概念**:Aidl是一种接口定义语言,它的主要作用是在Android应用的不同进程中定义和实现接口,使得服务可以被其他进程调用,实现跨进程通信。 2. **接口定义**:在Aidl文件中,我们可以定义接口(interface...

    进程间通信(aidl的使用)

    AIDL是Android提供的一个接口定义语言,它类似于Java,但专门用于描述进程间通信的接口。通过AIDL,开发者可以定义方法签名,指定参数类型和返回值,从而创建可以在进程间传递的对象。AIDL文件会被编译成Java代码,...

    android service、aidl教学

    本教程将详细讲解如何实现Android Service以及使用AIDL来创建远程服务。 首先,让我们深入了解Android的Service。Service是一种在后台运行的组件,即使用户没有直接与应用交互,它也能执行任务。Service可以用于...

    android-aidl:该项目使用Android AIDL创建远程服务

    在描述中,“该项目使用Android AIDL创建远程服务”进一步强调了AIDL在构建这样的系统中的核心作用。AIDL允许开发者定义接口,这些接口可以被不同的Android进程调用,从而实现服务与客户端之间的数据交换和服务调用...

    AIDL的简单例子

    AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理Android应用程序间的进程间通信(IPC, Inter-Process Communication)。通过AIDL,开发者可以定义服务(Service)与...

    Android365MobileSecretary v1.0.6(365手机助手AIDL).zip

    在Android应用开发中,AIDL(Android接口定义语言)是一种用于实现进程间通信(IPC, Inter-Process Communication)的工具。当两个Android进程需要交换数据时,通常会用到AIDL,比如服务与活动之间,或者跨应用通信...

    AIDL示例超赞的demo

    - **Android AIDL**:如上所述,是Android系统中实现进程间通信的语言,通过编写AIDL文件,可以定义接口,使得不同进程间的对象能够互相调用方法。 - **IPC(Inter-Process Communication)**:这是操作系统中的一个...

    AIDL最佳实践例子(2014年)

    这个2014年的最佳实践例子可能包含了如何创建、使用和优化AIDL的具体示例,对于理解AIDL的运作机制非常有帮助。随着Android的发展,虽然AIDL仍然是IPC的一种方式,但现代Android开发中更多地倾向于使用其他机制,如...

    安卓Android源码——aidl跨进程调用.zip

    AIDL是一种简单的接口定义语言,用于描述服务端提供的接口方法。当一个应用需要与另一个应用进行交互时,可以定义一个AIDL文件,声明服务端暴露的方法。AIDL文件通常以`.aidl`为扩展名,其语法类似于Java,但更精简...

    android AIDL简介

    - **定义**:AIDL(Android Interface Definition Language)是Android系统提供的一个接口定义语言,用于描述进程间通信(IPC)中不同应用组件如何进行交互的规则。 - **作用**:通过AIDL,开发者可以定义接口,使得...

    Android aidl文件

    AIDL是Android系统提供的接口定义语言,它允许开发者定义服务接口,使得客户端和服务端能够进行数据交换。AIDL文件本质上是一个简单的文本文件,后缀为.aidl,其中包含了方法声明、参数类型和返回值等信息。当...

    android安卓挂断电话,双卡挂断的aidl

    AIDL定义了一种接口,该接口描述了客户端和服务端之间可以交换的数据类型和方法。当客户端调用服务端的方法时,Android会自动处理跨进程调用的细节。在挂断电话的场景下,我们需要创建一个AIDL文件,声明一个服务...

    Android中如何利用AIDL机制调用远程服务

    在Android中,则采用AIDL(Android Interface DefinitionLanguage:接口描述语言)方式实现。 AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。...

Global site tag (gtag.js) - Google Analytics