搜索
您的当前位置:首页AIDL

AIDL

来源:乌哈旅游


官网介绍及示例:



     什么是AIDL

AIDL:Android Interface Definition Language,即Android接口描述语言。
Android系统中的进程之间不能 ,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了 (Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、Broadcast和Content Provider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

建立AIDL服务的步骤

建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。详细介绍见实例的内容。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。

Android AIDL使用详解

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

2.既然aidl可以定义并实现进程通信,那么我们怎么使用它呢?文档/android-sdk/docs/guide/developing/tools/aidl.html中对步骤作了详细描述:

--1.Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client. 
创建你的aidl文件,我在后面给出了一个例子,它的aidl文件定义如下:写法跟java代码类似,但是这里有一点值得注意的就是它可以引用其它aidl文件中定义的接口,但是不能够引用你的java类文件中定义的接口

[java] 

--2.Add the .aidl file to your makefile - (the ADT Plugin for Eclipse manages this for you). Android includes the compiler, called AIDL, in the tools/ directory. 
编译你的aidl文件,这个只要是在eclipse中开发,你的adt插件会像资源文件一样把aidl文件编译成java代码生成在gen文件夹下,不用手动去编译:编译生成AIDLService.java如我例子中代码

[java:showcolumns] 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. private final AIDLService.Stub mBinder = new AIDLService.Stub() {  
  2.   
  3.     @Override  
  4.     public void invokCallBack() throws RemoteException {  
  5.         Log("AIDLService.invokCallBack");  
  6.         Rect1 rect = new Rect1();  
  7.         rect.bottom=-1;  
  8.         rect.left=-1;  
  9.         rect.right=1;  
  10.         rect.top=1;  
  11.         callback.performAction(rect);  
  12.     }  
  13.   
  14.   
  15.     @Override  
  16.     public void registerTestCall(AIDLActivity cb) throws RemoteException {  
  17.         Log("AIDLService.registerTestCall");  
  18.         callback = cb;  
  19.     }  
  20. };  

Stub翻译成中文是存根的意思,注意Stub对象是在被调用端进程,也就是服务端进程,至此,服务端aidl服务端得编码完成了。

--4.Expose your interface to clients - If you're writing a service, you should extend Service and override Service.onBind(Intent) to return an instance of your class that implements your interface. 
第四步告诉你怎么在客户端如何调用服务端得aidl描述的接口对象,doc只告诉我们需要实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时不是需要一个ServiceConnection对象么,在没有了解aidl用法前一直不知道它是什么作用,其实他就是用来在客户端绑定service时接收service返回的IBinder对象的:

[java] 
  1. AIDLService mService;  
  2. private ServiceConnection mConnection = new ServiceConnection() {  
  3.     public void onServiceConnected(ComponentName className, IBinder service) {  
  4.         Log("connect service");  
  5.         mService = AIDLService.Stub.asInterface(service);  
  6.         try {  
  7.             mService.registerTestCall(mCallback);  
  8.         } catch (RemoteException e) {  
  9.   
  10.         }  
  11.     }  
  12.   
  13.   
  14.     public void onServiceDisconnected(ComponentName className) {  
  15.         Log("disconnect service");  
  16.         mService = null;  
  17.     }  
  18. };  

 

mService就是AIDLService对象,具体可以看我后面提供的示例代码,需要注意在客户端需要存一个服务端实现了的aidl接口描述文件,但是客户端只是使用该aidl接口,不需要实现它的Stub类,获取服务端得aidl对象后mService = AIDLService.Stub.asInterface(service);,就可以在客户端使用它了,对mService对象方法的调用不是在客户端执行,而是在服务端执行。

4.aidl中使用java类,需要实现Parcelable接口,并且在定义类相同包下面对类进行声明:

上面我定义了Rect1类
之后你就可以在aidl接口中对该类进行使用了
package com.cao.android.demos.binder.aidl;  
import com.cao.android.demos.binder.aidl.Rect1;
interface AIDLActivity {   
    void performAction(in Rect1 rect);   
}  
注意in/out的说明,我这里使用了in表示输入参数,out没有试过,为什么使用in/out暂时没有做深入研究。

5.aidl使用完整示例,为了清除说明aidl使用,我这里写了一个例子,例子参考了博客:

作出说明

例子实现了一个AIDLTestActivity,AIDLTestActivity通过bindservice绑定一个服务AIDLTestService,通过并获取AIDLTestActivity的一个aidl对象AIDLService,该对象提供两个方法,一个是registerTestCall注册一个aidl对象,通过该方法,AIDLTestActivity把本身实现的一个aidl对象AIDLActivity传到AIDLTestService,在AIDLTestService通过操作AIDLActivity这个aidl远端对象代理,使AIDLTestActivity弹出一个toast,完整例子见我上传的资源:

文章仓促而成,有什么疑问欢迎大家一起讨论


///


 



大家好,好久不见,今天要给大家分享的是android aidl的使用。在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享. 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦.  


AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.   

AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.  

 

今天的两个实例用到两个Android工程,一个是AIDL的服务端另一个是客户端。

 

服务端的实现步骤:

 

[java] 
  1. package com.chapter8.aidl;  
  2. import com.chapter8.aidl.Book;  
  3. interface IAIDLServerService {   
  4.       
  5.     String sayHello();  
  6.       
  7.     Book getBook();  
  8. }  
 

第二步:因为这个接口里有传递对象,所以对象要特殊处理一下,这里继承了Parcelable,Book.java代码如下:

如果大家不明的地方,请参见,下面连接的文章:

[java] 
  1. package com.chapter8.aidl;  
  2. import android.os.Parcel;  
  3. import android.os.Parcelable;  
  4. public class Book implements Parcelable {  
  5.       
  6.     private String bookName;  
  7.     private int bookPrice;  
  8.       
  9.     public Book(){  
  10.           
  11.     }  
  12.       
  13.     public Book(Parcel parcel){  
  14.         bookName = parcel.readString();  
  15.         bookPrice = parcel.readInt();  
  16.     }  
  17.       
  18.     public String getBookName() {  
  19.         return bookName;  
  20.     }  
  21.     public void setBookName(String bookName) {  
  22.         this.bookName = bookName;  
  23.     }  
  24.     public int getBookPrice() {  
  25.         return bookPrice;  
  26.     }  
  27.     public void setBookPrice(int bookPrice) {  
  28.         this.bookPrice = bookPrice;  
  29.     }  
  30.       
  31.     public int describeContents() {  
  32.         return 0;  
  33.     }  
  34.     public void writeToParcel(Parcel parcel, int flags) {  
  35.         parcel.writeString(bookName);  
  36.         parcel.writeInt(bookPrice);  
  37.     }  
  38.       
  39.     public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {  
  40.         public Book createFromParcel(Parcel source) {  
  41.               
  42.             return new Book(source);  
  43.         }  
  44.         public Book[] newArray(int size) {  
  45.             return new Book[size];  
  46.         }  
  47.     };  
  48. }  
 

第三步:写一个与Book类对应的aidl,命名为Book.aidl,代码非常简单,代码如下:

[java] 
  1. parcelable Book;  
 

第四步:新建一个名为AidlServerService的Service.代码如下:

[java] 
  1. package com.chapter8.aidl;  
  2. import com.chapter8.aidl.IAIDLServerService.Stub;  
  3. import com.chapter8.aidl.IAIDLServerService;  
  4. import android.app.Service;  
  5. import android.content.Intent;  
  6. import android.os.IBinder;  
  7. import android.os.RemoteException;  
  8. public class AidlServerService extends Service {  
  9.     @Override  
  10.     public IBinder onBind(Intent intent) {  
  11.         return mBinder;  
  12.     }  
  13.     /** 
  14.      * 在AIDL文件中定义的接口实现。 
  15.      */   
  16.     private IAIDLServerService.Stub mBinder = new Stub() {  
  17.           
  18.         public String sayHello() throws RemoteException {  
  19.             return "Hello";  
  20.         }  
  21.           
  22.         public Book getBook() throws RemoteException {  
  23.             Book mBook = new Book();  
  24.             mBook.setBookName("Android应用开发");  
  25.             mBook.setBookPrice(50);  
  26.             return mBook;  
  27.         }  
  28.     };  
  29. }  
 

第五步:在AndroidManifest.xml注册Service,代码如下:

[java] 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.chapter8.aidl"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name="AidlServerActivity"  
  8.                   android:label="@string/app_name">  
  9.             <intent-filter>  
  10.                 <action android:name="android.intent.action.MAIN" />  
  11.                 <category android:name="android.intent.category.LAUNCHER" />  
  12.             </intent-filter>  
  13.         </activity>  
  14.         <service android:name="AidlServerService"  
  15.                  android:process=":remote">  
  16.             <intent-filter>  
  17.                 <action android:name="com.chapter8.aidl.IAIDLServerService"></action>  
  18.             </intent-filter>  
  19.         </service>  
  20.     </application>  
  21. </manifest>  
 

第六步:运行服务端工程,到设备上,好让客户端调用,服务端的Activity什么都没做.效果如下:

客户端的具体实现步骤:


第二步:引入Aidl文件以及用到的类,如上面的com.chapter8.aidl包。直接从服务端里代码copy过来就OK.

第三步:修改main.xml布局文件,增加一个按钮,代码如下:

[java] 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <TextView    
  8.     android:id="@+id/textview"  
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"   
  11.     android:text="@string/hello"  
  12.     />  
  13. <Button  
  14.     android:id="@+id/button"  
  15.     android:layout_width="fill_parent"  
  16.     android:layout_height="wrap_content"  
  17.     android:text="调用AIDL服务"  
  18.     />  
  19. </LinearLayout>  
 

第四步:修改AidlClientActivity.java代码如下:

[java] 
  1. package com.chapter8.aidlclient;  
  2. import com.chapter8.aidl.IAIDLServerService;  
  3. import android.app.Activity;  
  4. import android.content.ComponentName;  
  5. import android.content.Intent;  
  6. import android.content.ServiceConnection;  
  7. import android.os.Bundle;  
  8. import android.os.IBinder;  
  9. import android.os.RemoteException;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.Button;  
  13. import android.widget.TextView;  
  14. public class AidlClientActivity extends Activity {  
  15.    
  16.     private TextView mTextView;  
  17.     private Button mButton;  
  18.       
  19.     private IAIDLServerService mIaidlServerService = null;  
  20.       
  21.     private ServiceConnection mConnection = new ServiceConnection() {  
  22.           
  23.         public void onServiceDisconnected(ComponentName name) {  
  24.             mIaidlServerService = null;  
  25.         }     
  26.         public void onServiceConnected(ComponentName name, IBinder service) {  
  27.             mIaidlServerService = IAIDLServerService.Stub.asInterface(service);  
  28.             //aidl通信  
  29.             try {  
  30.                 String mText = "Say hello: " + mIaidlServerService.sayHello() + "/n";  
  31.                 mText += "书名: " + mIaidlServerService.getBook().getBookName()+"/n";  
  32.                 mText += "价格: " + mIaidlServerService.getBook().getBookPrice();  
  33.                 mTextView.setText(mText);  
  34.             } catch (RemoteException e) {  
  35.                 e.printStackTrace();  
  36.             }  
  37.         }  
  38.     };  
  39.       
  40.     @Override  
  41.     public void onCreate(Bundle savedInstanceState) {  
  42.         super.onCreate(savedInstanceState);  
  43.         setContentView(R.layout.main);        
  44.         //初始化控件  
  45.         mTextView = (TextView)findViewById(R.id.textview);  
  46.         mButton = (Button)findViewById(R.id.button);  
  47.         //增加事件响应  
  48.         mButton.setOnClickListener(new OnClickListener(){  
  49.             public void onClick(View v) {  
  50.                 //bindService  
  51.                 Intent service = new Intent("com.chapter8.aidl.IAIDLServerService");  
  52.                 bindService(service, mConnection,BIND_AUTO_CREATE);                           
  53.             }  
  54.               
  55.         });  
  56.     }  
  57.       
  58.       
  59. }  
 

第五步:运行客户端工程,效果如下:

Ok,上面就完整的作了一个Aidl开发的流程,有什么不对的地方希望大家多多指教,今天就讲到这里



///

“AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做更一步处理。AIDL服务支持的数据类型如下:

Java的简单类型(int、char、boolean等)。不需要导入(import)。

String和CharSequence。不需要导入(import)。

List和Map。但要注意,List和Map对象的元素类型必须是AIDL服务支持的数据类型。不需要导入(import)。

AIDL自动生成的接口。需要导入(import)。

实现android.os.Parcelable接口的类。需要导入(import)。

其中后两种数据类型需要使用import进行导入,将在本章的后面详细介绍。

传递不需要import的数据类型的值的方式相同。传递一个需要import的数据类型的值(例如,实现android.os.Parcelable接口的类)的步骤略显复杂。除了要建立一个实现android.os.Parcelable接口的类外,还需要为这个类单独建立一个aidl文件,并使用parcelable关键字进行定义。”



///

 

分类:    131人阅读  (0)   

       在做进程间通信时,使用系统aidl文件。 我把这个文件夹(包括aidl文件)拷贝到项目, 居然不自动生成aidl.java.

1、解决方案: 在aidl包下、新建一个合格的aidl文件, 新建的aidl可以自动生成aidl.java。  再删除系统aidl.     再粘贴系统aidl 放到包里。他就会自动生成aidl.java了。




官网介绍:



因篇幅问题不能全部显示,请点此查看更多更全内容

Top