android进程间通信——aidl(Android Interface Definition Language)

本文详细介绍Android中AIDL(Android Interface Definition Language)用于实现不同进程间的通信原理及步骤。从设计AIDL接口开始,通过定义接口、实现接口、暴露接口给用户等步骤,再到实现对象跨进程传递,最后展示如何在客户端调用服务端提供的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在android中,通常情况下一个进程是不允许其它进程访问自己的内存的。而aidl提供了client和service都“同意”的交互接口,用以实现进程间通信。

使用aidl通常有三个阶段:

由于创建的是两个应用程序,为了方便介绍,这里先给出服务提供者(Service)的工程目录结构图:

一、aidl的设计——设计aidl包括三个步骤:

1、定义aidl

在设计好aidl接口后,就可以编写aidl文件了。aidl文件编写的语法和java语言的语法一样——后缀名改为.aidl,然后同时将它保存到服务提供者(service)服务使用者(client)的源代码(src/derectory)目录下。

在上面的目录中,包含了两个aidl文件。其中,IDescribePerson.aidl是重点;Person.aidl是系统的需求,必须定义。

2、实现定义的aidl接口

android SDK 工具会为任何包含有.aidl文件的应用程序生成一个IBinder接口。根据.aidl文件生成的IBinder接口会保存在目录(gen/directory)下,该接口包含一个继承自Binder 的内部类—Stub。你只需要继承Stub类并实现该类的方法即可。

在上面目录中,RemoteService.java继承自Service,其中一成员变量mBinder为IDescribePerson.Stub的实现。

3、将接口暴露给用户

实现一个Service并且复写onBind()方法,该方法返回Stub类的实现类的实例。

RemoteService的onBind()方法返回mBinder

(注意事项:aidl仅支持几种数据类型,包括:java所有的基本数据类型、String、CharSequence、List、Map、(Serializable、Parceable, 及其实现类))

进程间传递对象(Passing Objects Over IPC)

要实现进程间对象的传递,则该对象必须支持Parceable——类要实现Parceable接口。

上图中,类Person实现了Parceable接口。

三、调用进程通信方法(calling an IPC Method)——包括7个步骤:

下面将会用到client的相关内容,这里先将client目录结构图给出:

1、确保应用程序包含了aidl文件(如果嫌麻烦,可以直接将cxy.sh.aidl.server包下得内容直接拷贝过来)。

2、声明一个IBinder 的实例(该实例是基于AIDL文件生成的)。

3、实现ServiceConnection。

4、调用bindService(),传递参数ServiceConnection的实现。

5、在实现onServiceConnected()方法时,调用YourInterfaceName.Stub.asInterface((IBinder)service)返回接口

6、调用接口中声明的方法。

7、调用方法 Context.unbindService()  断开与服务的连接。    

下面给出各文件的源码(文件内容是eclipse自动生成的就不贴了):

aidlTest应用:

Person.java

package cxy.sh.aidl.server;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private String name ;
private String telNumber ;
private int age;
public Person(Parcel p){
name = p.readString();
telNumber = p.readString();
age = p.readInt();
}
public Person(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTelNumber() {
return telNumber;
}
public void setTelNumber(String telNumber) {
this.telNumber = telNumber;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int arg1) {
dest.writeString(name);
dest.writeString(telNumber);
dest.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
@Override 
public Person createFromParcel(Parcel source){
return new Person(source);
}
@Override
public Person[] newArray(int size){
return new Person[size];
}
};
}


RemoteService.java

package cxy.sh.aidl.server;
import java.util.LinkedList;
import java.util.List;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
private LinkedList<Person> pList = new LinkedList<Person>();

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IDescribePerson.Stub mBinder = new IDescribePerson.Stub(){

@Override
public void savePersonInfo(Person person) throws RemoteException{
if(person != null){
pList.add(person);
}
}
@Override
public List<Person> getAllPerson() throws RemoteException{
return pList;
}
};
}


IDescribePerson.aidl

package cxy.sh.aidl.server;
import cxy.sh.aidl.server.Person;
interface IDescribePerson{
void savePersonInfo(in Person person);
List<Person> getAllPerson();
}


Person.aidl

package cxy.sh.aidl.server;
parcelable Person;

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cxy.sh.aidl.server"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="14" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".AidlTestActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="RemoteService" >  
            <intent-filter>  
                <action android:name="cxy.sh.aidl.server.IDescribePerson"></action>  
            </intent-filter>  
        </service>  
    </application>
</manifest>


aidlClient应用:

AidlClientActivity.java

package cxy.sh.aidl.client;
import java.util.List;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import cxy.sh.aidl.server.IDescribePerson;
import cxy.sh.aidl.server.Person;
public class AidlClientActivity extends Activity {
private Button addPersonButton;
private Button listPersonButton;
private TextView inputPersonEdit;
private IDescribePerson mRemoteService ;
private ServiceConnection mRemoteCon = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteService = IDescribePerson.Stub.asInterface(service);
inputPersonEdit.setText("remote Servece connected !");
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteService = null ;
Log.e("tag", "remote Servece disconnected !");
}

};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        new Thread(new Runnable(){
@Override
public void run() {
Intent service = new Intent("cxy.sh.aidl.server.IDescribePerson");  
                bindService(service, mRemoteCon,BIND_AUTO_CREATE);  ;
}
        }).start();
        addPersonButton = (Button) findViewById(R.id.btadd);
        listPersonButton = (Button) findViewById(R.id.btlist);
        inputPersonEdit = (TextView) findViewById(R.id.tv) ;
        addPersonButton.setOnClickListener( 
                new View.OnClickListener(){ 
                        private int index = 0; 
                        @Override 
                        public void onClick(View view) { 
                                Person person = new Person(); 
                                index = index + 1; 
                                person.setName("person-->" + index); 
                                person.setAge(20+index); 
                                person.setTelNumber("123456-"+index); 
                                try { 
                                        mRemoteService.savePersonInfo(person); 
                                } catch (RemoteException e) { 
                                        e.printStackTrace(); 
                                } 
                        } 
                }); 
        listPersonButton.setOnClickListener( 
                new View.OnClickListener(){ 
                        @Override 
                        public void onClick(View view) { 
                                List<Person> list = null; 
                                try { 
                                        list = mRemoteService.getAllPerson(); 
                                } catch (RemoteException e) { 
                                        e.printStackTrace(); 
                                } 
                                if (list != null){ 
                                        StringBuilder text = new StringBuilder(); 
                                        for(Person person : list){ 
                                                text.append("\n联系人姓名:"); 
                                                text.append(person.getName()); 
                                                text.append("\n             年龄 :"); 
                                                text.append(person.getAge()); 
                                                text.append("\n 电话号码:"); 
                                                text.append(person.getTelNumber()+"\n"); 
                                        } 
                                        inputPersonEdit.setText(text); 
                                }else { 
                                        Toast.makeText(AidlClientActivity.this, "get data error", 
                                                        Toast.LENGTH_SHORT).show(); 
                                } 
                        } 
                });
    }
@Override
protected void onPause() {
super.onPause();
unbindService(mRemoteCon);
}
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值