Android 中的AIDL

本文介绍Android中AIDL的使用方法,包括创建接口、实现服务端与客户端交互等步骤。

大家好,好久不见,今天要给大家分享的是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的服务端另一个是客户端。

 

服务端的实现步骤:

首先看一下服务端,工程目录如下:

首先创建IaidlServerService.aidl文件,代码如下(一个简单方法,另一个返回对象方法),当我们点击保存时会在gen目录下生成对应的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代码如下:

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

Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!

  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,代码非常简单,代码如下:

  1. parcelable Book;  
 

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

  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,代码如下:

  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布局文件,增加一个按钮,代码如下:

  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代码如下:

  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开发的流程,有什么不对的地方希望大家多多指教,今天就讲到这里。谢谢!

<think>好的,我现在需要回答用户关于如何在Android中实现AIDL接口定义语言的问题。首先,我得回忆一下AIDL的基本概念和用途。AIDL,全称是Android Interface Definition Language,主要用于不同进程间的通信,也就是IPC。用户可能已经知道AIDL的一些基本语法,但具体实现步骤可能需要详细说明。 根据用户提供的引用内容,我需要整合这些信息。引用1提到AIDLJava的差异,比如文件后缀是.aidl,而不是.java。引用2指出必须用Java构建AIDL文件,每个文件定义一个接口。引用3说明SDK工具会生成.java接口文件,包含Stub子类。引用4提到Proxy和BinderProxy的流程。这些引用都是关键点,需要融入到回答中。 接下来,我应该分步骤解释实现过程。第一步是创建AIDL文件,需要说明文件的位置和结构。比如,在Android Studio中,通常放在src/main/aidl目录下,并且包结构要和Java包一致。然后,定义接口方法,比如声明一个add方法,参数和返回类型需要正确。 第二步是构建项目,让SDK工具生成对应的Java接口。这里需要提到生成的Stub类,它是抽象类,实现IBinder接口,并包含服务端需要实现的方法。同时,Proxy类处理客户端的调用,将参数序列化并发送到服务端。 第三步是实现Service,继承自Service类,并实现Stub中的抽象方法。这里要强调在onBind方法中返回Stub的实例,并且Stub本身是Binder的子类,所以可以直接返回。 第四步是客户端绑定服务,使用bindService方法,并通过asInterface将IBinder对象转换为接口实例。这时候客户端就可以调用远程方法了。 另外,需要注意数据类型的支持,AIDL默认支持基本类型、String、List、Map等,如果要传递自定义对象,需要实现Parcelable接口,并在AIDL文件中导入。这一点用户可能容易忽略,需要特别说明。 可能还需要提到AIDL的一些限制,比如方法不能重载,参数的方向标记(in, out, inout),以及异常处理机制。不过用户的问题集中在实现方式上,可能不需要太深入,但可以简要提及。 在回答过程中,需要引用用户提供的引用内容。例如,在创建AIDL文件时,引用1和2关于文件类型和Java语法的内容;生成接口时引用3的Stub和Proxy;客户端调用时引用4提到的BinderProxy流程。 最后,要确保回答结构清晰,分步骤说明,并且每个步骤都有对应的代码示例。同时,生成的相关问题要围绕AIDL的实现细节、使用场景和优化方法展开,帮助用户进一步学习。</think>### AndroidAIDL接口定义语言的实现方式 #### 1. **AIDL文件定义** - **文件类型与位置**:AIDL文件以`.aidl`为后缀,需放置在项目的`src/main/aidl`目录下,包路径需与Java包名一致。例如,定义接口`IMathService.aidl`: ```aidl // IMathService.aidl package com.example.aidl; interface IMathService { int add(int a, int b); } ``` 此处声明了一个支持跨进程调用的`add`方法[^1][^2]。 - **支持的数据类型**:AIDL默认支持基本类型、`String`、`List`、`Map`等。若需传递自定义对象,需实现`Parcelable`接口并在AIDL文件中导入(例如`parcelable MyData;`)。 --- #### 2. **生成Java接口** - **编译构建**:Android SDK工具会根据AIDL文件自动生成对应的Java接口(如`IMathService.java`),其中包含: - **Stub类**:抽象类`IMathService.Stub`继承自`Binder`并实现`IMathService`接口,需在服务端实现其抽象方法(如`add`)。 - **Proxy类**:内部类`Proxy`负责客户端请求的序列化与Binder通信[^3]。 --- #### 3. **服务端实现** - **Service类编写**:创建`Service`子类并实现`Stub`的抽象方法: ```java public class MathService extends Service { private final IMathService.Stub binder = new IMathService.Stub() { @Override public int add(int a, int b) { return a + b; } }; @Override public IBinder onBind(Intent intent) { return binder; // 返回Stub实例 } } ``` `Stub`本质是`Binder`的子类,可直接作为`onBind()`的返回值[^3]。 --- #### 4. **客户端绑定与调用** - **绑定服务**:客户端通过`bindService()`连接服务,并通过`asInterface()`将`IBinder`转换为接口实例: ```java private IMathService mathService; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mathService = IMathService.Stub.asInterface(service); // 转换为接口 } // ...onServiceDisconnected }; ``` - **远程调用**:通过`mathService.add(2,3)`即可跨进程调用服务端方法,实际由`Proxy`类处理参数序列化和Binder通信[^4]。 --- #### 关键机制说明 - **Binder驱动**:AIDL底层依赖Binder驱动完成跨进程数据传输,客户端调用通过`Proxy`封装为`Parcel`对象,经Binder传递到服务端`Stub`解析后执行。 - **线程模型**:AIDL方法默认在Binder线程池调用,若需操作UI,需切换至主线程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值