`

Android Interface Definition Language(AIDL)

 
阅读更多

<!-- [if gte mso 9]><xml><w:WordDocument><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery><w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery><w:DocumentKind>DocumentNotSpecified</w:DocumentKind><w:DrawingGridVerticalSpacing>7.8</w:DrawingGridVerticalSpacing><w:View>Normal</w:View><w:Compatibility></w:Compatibility><w:Zoom>0</w:Zoom></w:WordDocument></xml><![endif]-->

使用AIDL 设计远程接口 ( Designing a Remote Interface Using AIDL )

由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI 运行另一个服务进程,而且经常会在不同的进程间传递对象。在 Android 平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。

通过代码来实现这个数据传输过程是冗长乏味的,Android 提供了 AIDL 工具来处理这项工作。

AIDL (Android Interface Definition Language)是一种 IDL  语言,用于生成可以在 Android 设备上两个进程之间进行进程间通信 (IPC) 的代码。如果在一个进程中(例如 Activity )要调用另一个进程中(例如 Service )对象的操作,就可以使用 AIDL 生成可序列化的参数。

AIDL IPC机制是面向接口的,像 COM Corba 一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

 

使用AIDL 实现 IPC( Implementing IPC Using AIDL )

使用AIDL 实现 IPC 服务的步骤是:

1.  创建.aidl 文件 - 该文件( YourInterface.aidl )定义了客户端可用的方法和数据的接口。

2.  makefile 文件中加入 .aidl 文件 - Eclipse 中的 ADT 插件提供管理功能) Android 包括名为 AIDL 的编译器,位于 tools/ 文件夹。

3.  实现接口-AIDL 编译器从 AIDL 接口文件中利用 Java 语言创建接口,该接口有一个继承的命名为 Stub 的内部抽象类(并且实现了一些 IPC 调用的附加方法),要做的就是创建一个继承于 YourInterface.Stub 的类并且实现在 .aidl 文件中声明的方法。

4.  向客户端公开接口- 如果是编写服务,应该继承 Service 并且重载 Service.onBind(Intent)  以返回实现了接口的对象实例

 

创建.aidl 文件 ( Create an .aidl File )

AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他 AIDL 生成的接口。重要的是必须导入所有非内置类型,哪怕是这些类型是在与接口相同的包中。下面是 AIDL 能支持的数据类型:

Java编程语言的主要类型  (int, boolean — 不需要  import  语句。

以下的类 ( 不需要 import  语句 ):

String

List  - 列表中的所有元素必须是在此列出的类型,包括其他AIDL 生成的接口和可打包类型。 List 可以像一般的类(例如 List<String> )那样使用,另一边接收的具体类一般是一个 ArrayList ,这些方法会使用 List 接口。

Map  -  Map中的所有元素必须是在此列出的类型,包括其他 AIDL 生成的接口和可打包类型。一般的 maps (例如 Map<String,Integer> )不被支持,另一边接收的具体类一般是一个 HashMap ,这些方法会使用 Map 接口。

CharSequence  - 该类是被TextView 和其他控件对象使用的字符序列。

通常引引用方式传递的其他AIDL 生成的接口,必须要 import  语句声明

实现了Parcelable protocol  以及按值传递的自定义类,必须要 import  语句声明。

以下是基本的AIDL 语法:

,

 

实现接口( Implementing the Interface )

AIDL生成了与 .aidl 文件同名的接口,如果使用 Eclipse 插件, AIDL 会做为编译过程的一部分自动运行(不需要先运行 AIDL 再编译项目),如果没有插件,就要先运行 AIDL

生成的接口包含一个名为Stub 的抽象的内部类,该类声明了所有 .aidl 中描述的方法, Stub 还定义了少量的辅助方法,尤其是 asInterface() ,通过它或以获得 IBinder (当 applicationContext.bindService() 成功调用时传递到客户端的 onServiceConnected() )并且返回用于调用 IPC 方法的接口实例,更多细节参见 Calling an IPC Method

要实现自己的接口,就从YourInterface.Stub 类继承,然后实现相关的方法(可以创建 .aidl 文件然后实现 stub 方法而不用在中间编译, Android 编译过程会在 .java 文件之前处理 .aidl 文件)。

这个例子实现了对IRemoteService 接口的调用,这里使用了匿名对象并且只有一个 getPid() 接口。

这里是实现接口的几条说明:

不会有返回给调用方的异常

默认IPC 调用是同步的。如果已知 IPC 服务端会花费很多毫秒才能完成,那就不要在 Activity View 线程中调用,否则会引起应用程序挂起( Android 可能会显示“应用程序未响应”对话框),可以试着在独立的线程中调用。

AIDL接口中只支持方法,不能声明静态成员。

 

向客户端暴露接口( Exposing Your Interface to Clients )

在完成了接口的实现后需要向客户端暴露接口了,也就是发布服务,实现的方法是继承 Service ,然后实现以 Service.onBind(Intent) 返回一个实现了接口的类对象。下面的代码片断表示了暴露 IRemoteService 接口给客户端的方式。

public   class   RemoteService   extends   Service   {

...

@Override

     public   IBinder  onBind ( Intent  intent )   {

         // Select the interface to return.  If your service only implements

         // a single interface, you can just return it here without checking

         // the Intent.

         if   ( IRemoteService . class . getName (). equals ( intent . getAction ()))   {

             return  mBinder ;

         }

         if   ( ISecondary . class . getName (). equals ( intent . getAction ()))   {

             return  mSecondaryBinder ;

         }

         return   null ;

     }

 

     /**

     * The IRemoteInterface is defined through IDL

     */

     private   final   IRemoteService . Stub  mBinder  =   new   IRemoteService . Stub ()   {

         public   void  registerCallback ( IRemoteServiceCallback  cb )   {

             if   ( cb  !=   null )  mCallbacks . register ( cb );

         }

         public   void  unregisterCallback ( IRemoteServiceCallback  cb )   {

             if   ( cb  !=   null )  mCallbacks . unregister ( cb );

         }

     };

 

     /**

     * A secondary interface to the service.

     */

     private   final   ISecondary . Stub  mSecondaryBinder  =   new   ISecondary . Stub ()   {

         public   int  getPid ()   {

             return   Process . myPid ();

         }

         public   void  basicTypes ( int  anInt ,   long  aLong ,   boolean  aBoolean ,

                 float  aFloat ,   double  aDouble ,   String  aString )   {

         }

     };

 

}

 

使用可打包接口传递参数 Pass by value Parameters using Parcelables

如果有类想要能过AIDL 在进程之间传递,这一想法是可以实现的,必须确保这个类在 IPC 的两端的有效性,通常的情形是与一个启动的服务通信。

这里列出了使类能够支持Parcelable 4 个步骤:【译者注:原文为 5 ,但列表为 4 项,疑为作者笔误】

1.  使该类实现Parcelabel 接口。

2.  实现public void writeToParcel(Parcel out)  方法,以便可以将对象的当前状态写入包装对象中。

3.  增加名为CREATOR 的构造器到类中,并实现 Parcelable.Creator 接口。

4.  最后,但同样重要的是,创建AIDL 文件声明这个可打包的类(见下文),如果使用的是自定义的编译过程,那么不要编译此 AIDL 文件,它像 C 语言的头文件一样不需要编译。

AIDL会使用这些方法的成员序列化和反序列化对象。

这个例子演示了如何让Rect 类实现 Parcelable 接口。

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 ();

}

}

这个是Rect.aidl 文件。

序列化Rect 类的工作相当简单,对可打包的其他类型的数据可以参见 Parcel 类。

警告 :不要忘了对从其他进程接收到的数据进行安全检查。在上面的例子中,rect 要从数据包中读取 4 个数值,需要确认无论调用方想要做什么,这些数值都是在可接受的范围之内。想要了解更多的关于保持应用程序安全的内容,可参见  Security and Permissions

 

调用IPC 方法 (Calling an IPC Method)

这里给出了调用远端接口的步骤:

1.  声明.aidl 文件中定义的接口类型的变量。

2.  实现ServiceConnection

3.  调用Context.bindService() ,传递 ServiceConnection 的实现

4.  ServiceConnection.onServiceConnected() 方法中会接收到 IBinder 对象,调用 YourInterfaceName.Stub.asInterface((IBinder)service) 将返回值转换为 YourInterface 类型

5.  调用接口中定义的方法。应该总是捕获连接被打断时抛出的DeadObjectException 异常,这是远端方法唯一的异常。

6.  调用Context.unbindService() 断开连接

这里是几个调用IPC 服务的提示:

对象是在进程间进行引用计数

可以发送匿名对象作为方法参数

以下是演示调用AIDL 创建的服务,可以在 ApiDemos 项目中获取远程服务的示例。

public   static   class   Binding   extends   Activity   {

/** The primary interface we will be calling on the service. */

IRemoteService  mService  =   null ;

/** Another interface we use on the service. */

ISecondary  mSecondaryService  =   null ;

Button  mKillButton ;

TextView  mCallbackText ;

private   boolean  mIsBound ;

/**

* Standard initialization of this activity.  Set up the UI, then wait

* for the user to poke it before doing anything.

*/

@Override

protected   void  onCreate ( Bundle  savedInstanceState )   {

     super . onCreate ( savedInstanceState );

    setContentView ( R . layout . remote_service_binding );

     // Watch for button clicks.

     Button  button  =   ( Button ) findViewById ( R . id . bind );

    button . setOnClickListener ( mBindListener );

    button  =   ( Button ) findViewById ( R . id . unbind );

    button . setOnClickListener ( mUnbindListener );

    mKillButton  =   ( Button ) findViewById ( R . id . kill );

    mKillButton . setOnClickListener ( mKillListener );

    mKillButton . setEnabled ( false ); 

 

    mCallbackText  =   ( TextView ) findViewById ( R . id . callback );

   mCallbackText . setText ( "Not attached." );

}

 

/**

  * Class for interacting with the main interface of the service.

  */

private   ServiceConnection  mConnection  =   new   ServiceConnection ()   {

    public   void  onServiceConnected ( ComponentName  className ,   IBinder  service )   {

         // This is called when the connection with the service has been

         // established, giving us the service object we can use to

         // interact with the service.  We are communicating with our

         // service through an IDL interface, so get a client-side

         // representation of that from the raw service object.

        mService  =   IRemoteService . Stub . asInterface ( service );

        mKillButton . setEnabled ( true );

        mCallbackText . setText ( "Attached." );

 

         // We want to monitor the service for as long as we are

         // connected to it.

         try   {

                mService . registerCallback ( mCallback );

         }   catch   ( RemoteException  e )   {

             // In this case the service has crashed before we could even

             // do anything with it; we can count on soon being

             // disconnected (and then reconnected if it can be restarted)

             // so there is no need to do anything here.

         }

 

        // As part of the sample, tell the user what happened.

        Toast . makeText ( Binding . this ,  R . string . remote_service_connected ,

              Toast . LENGTH_SHORT ). show ();

     }

 

     public   void  onServiceDisconnected ( ComponentName  className )   {

         // This is called when the connection with the service has been

         // unexpectedly disconnected -- that is, its process crashed.

        mService  =   null ;

        mKillButton . setEnabled ( false );

        mCallbackText . setText ( "Disconnected." );

 

         // As part of the sample, tell the user what happened.

         Toast . makeText ( Binding . this ,  R . string . remote_service_disconnected ,

              Toast . LENGTH_SHORT ). show ();

     }

};

 

/**

  * Class for interacting with the secondary interface of the service.

  */

private   ServiceConnection  mSecondaryConnection  =   new   ServiceConnection ()   {

    public   void  onServiceConnected ( ComponentName  className ,  IBinder  service )   {

         // Connecting to a secondary interface is the same as any

         // other interface.

        mSecondaryService  =   ISecondary . Stub . asInterface ( service );

        mKillButton . setEnabled ( true );

     }

 

     public   void  onServiceDisconnected ( ComponentName  className )   {

        mSecondaryService  =   null ;

        mKillButton . setEnabled ( false );

     }

};

 

private   OnClickListener  mBindListener  =   new   OnClickListener ()   {

    public   void  onClick ( View  v )   {

         // Establish a couple connections with the service, binding

         // by interface names.  This allows other applications to be

         // installed that replace the remote service by implementing

         // the same interface.

       bindService ( new   Intent ( IRemoteService . class . getName ()),

              mConnection ,   Context . BIND_AUTO_CREATE );

            bindService ( new   Intent ( ISecondary . class . getName ()),

             mSecondaryConnection ,   Context . BIND_AUTO_CREATE );

         mIsBound  =   true ;

         mCallbackText . setText ( "Binding." );

     }

};

 

private   OnClickListener  mUnbindListener  =   new   OnClickListener ()   {

     public   void  onClick ( View  v )   {

        if   ( mIsBound )   {

             // If we have received the service, and hence registered with

             // it, then now is the time to unregister.

             if   ( mService  !=   null )   {

                  try   {

                     mService . unregisterCallback ( mCallback );

                  }   catch   ( RemoteException  e )   {

                     // There is nothing special we need to do if the service

                     // has crashed.

                 }

            }

 

            // Detach our existing connection.

            unbindService ( mConnection );

            unbindService ( mSecondaryConnection );

            mKillButton . setEnabled ( false );

            mIsBound  =   false ;

            mCallbackText . setText ( "Unbinding." );

        }

    }

};

 

private   OnClickListener  mKillListener  =   new   OnClickListener ()   {

     public   void  onClick ( View  v )   {

          // To kill the process hosting our service, we need to know its

          // PID.  Conveniently our service has a call that will return

          // to us that information.

          if   ( mSecondaryService  !=   null )   {

              try   {

                 int  pid  =  mSecondaryService . getPid ();

                 // Note that, though this API allows us to request to

                 // kill any process based on its PID, the kernel will

                 // still impose standard restrictions on which PIDs you

                 // are actually able to kill.  Typically this means only

                 // the process running your application and any additional

                 // processes created by that app as shown here; packages

                 // sharing a common UID will also be able to kill each

                 // other's processes.

                 Process . killProcess ( pid );
                    mCallbackText . setText ( "Killed service process." );

           }   catch   ( RemoteException  ex )   {

                 // Recover gracefully from the process hosting the

                 // server dying.

                 // Just for purposes of the sample, put up a notification.

                 Toast . makeText ( Binding . this ,

                       R . string . remote_call_failed ,

                        Toast . LENGTH_SHORT ). show ();

                 }

             }

         }

     };

 

// ----------------------------------------------------------------------

  // Code showing how to deal with callbacks.

  // ----------------------------------------------------------------------

 

/**

  * This implementation is used to receive callbacks from the remote

  * service.

*/

private   IRemoteServiceCallback  mCallback  =   new   IRemoteServiceCallback . Stub ()   {

    /**

     * This is called by the remote service regularly to tell us about

     * new values.  Note that IPC calls are dispatched through a thread

     * pool running in each process, so the code executing here will

     * NOT be running in our main thread like most other things -- so,

     * to update the UI, we need to use a Handler to hop over there.

    */

    public   void  valueChanged ( int  value )   {

       mHandler . sendMessage ( mHandler . obtainMessage ( BUMP_MSG ,  value ,   0 ));

    }

};

private   static   final   int  BUMP_MSG  =   1 ;

private   Handler  mHandler  =   new   Handler ()   {

    @Override   public   void  handleMessage ( Message  msg )   {

        switch   ( msg . what )   {

            case  BUMP_MSG :

               mCallbackText . setText ( "Received from service: "   +  msg . arg1 );

                break ;

            default :

                super . handleMessage ( msg );

         }

    }

};

}

 

 

原文 <!-- [if gte mso 9]><xml><w:WordDocument><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery><w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery><w:DocumentKind>DocumentNotSpecified</w:DocumentKind><w:DrawingGridVerticalSpacing>7.8</w:DrawingGridVerticalSpacing><w:View>Normal</w:View><w:Compatibility></w:Compatibility><w:Zoom>0</w:Zoom></w:WordDocument></xml><![endif]-->

http://developer.android.com/guide/developing/tools/a idl .html  ( 注意:3.0 r1  以后移到 Appendix )

 

分享到:
评论

相关推荐

    AIDL示例(Android Interface Definition Language)

    为了使其他的应用程序也可以访问本应用程序...因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。博客地址:http://blog.csdn.net/u013293125/article/details/77368261

    Android项目之AidlDemo(简单aidl的例子)

    Android项目之AidlDemo(简单的aidl的例子)。AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写。需要的小伙伴自请下载。

    AIDL最简单的使用步骤

    AIDL:Android Interface Definition Language,即Android接口定义语言。 为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他...

    Android Studio AIDL实现跨进程通信

    AIDL:Android Interface Definition Language,即Android接口定义语言. android studio中使用aidl实现跨进程通讯,具体步骤如下

    Android Studio实现Service AIDL

    为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android接口定义语言)。 建立两个Android项目,...

    Android AIDL使用详解

    aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 icp:interprocess communication :内部进程通信

    Android aidl-sample.zip

    AIDL(Android Interface Definition Language)示例程序,实现了在 Android 上的进程间通信(IPC),包含客户端和服务端代码。

    Android中两个APP之间的AIDL调用测试.rar

    ①Android Interface definition language(aidl,android接口定义语言),其目的实现跨进程的调用。进程是程序在os中执行的载体,一个程序对应一个进程,不同进程就是指不同程序,aidl实现不同程序之间的调用。 ②...

    AIDL服务器端和客户端

    AIDL是Android Interface definition language的缩写;它是一种接口定义语言,用来约束两个进程间通讯(IPC)的规则,供编译器生成代码,实现Android设备上两个进程间通讯(IPC),进程之间通讯的信息,首先会被转换...

    Android 进程间通信AIDL使用详解

    AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。从某种意义上说AIDL其实是一个模板,因为在...

    Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)

    AIDL:Android Interface Definition Language,翻译过来就是Android接口定义语言。是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。所以使用AIDL需要一个服务端和客户端 作用:可以在...

    Android-AIDL文件实现两个工程之间互相传输

    AIDL概述:AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言,设计这门语言的目的是为了实现进程间通信。接下来我写了两个demo(AildeService和AidleClient),他们之间...

    android中aidl的使用

    aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

    xamarin学习笔记A19(安卓AIDL)

    AIDL(Android Interface Definition Language)翻译为安卓接口定义语言,用于IPC(Inter-Process Communication)进程间通信。

    android aidl 教程

    整理30分钟 写了两个工程 aidlServer aidlClient 深入理解 android aidl 操作原理 android aidl 功能在 billing 、第三方支付、远程调用 等方面使用的比较普遍,深入理解android原理必须掌握。

    android aidl demo

    aidl 入门例子 在Android 中有一种服务说是服务其实倒不如说是一个接口,这个接口名为:Android Interface Definition Language ,这个接口可提供跨进程访问服务,英文缩写为:AIDL。

    aidl代码.zip

    文章里涉及到到代码,包含客户端,服务端代码,可直接导入到android studio运行...AIDL全称是Android Interface Definition Language,是安卓接口定义的意思,通过定义相关的接口来实现跨进程通信。

    AIDL跨进程调用Demo

    AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写,对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP...

    AIDL跨进程通信Demo

    aidl:aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 Demo中包含服务端和客户端 原文链接:...

    Android AIDL接口定义语言

    在Windows系统中存在IPC管道服务、MailSolt邮槽、消息等方法,在Android平台上提供了一种中间层语言 AIDL Android接口定义语言(Android Interface Definition Language)。  实现IPC服务通过使用AIDL步骤主要有: ...

Global site tag (gtag.js) - Google Analytics