Android 进程间通信(IPC)---AIDL入门

本文介绍如何使用Android Interface Definition Language (AIDL)实现跨进程通信(IPC),包括客户端和服务端的搭建过程,自定义对象序列化及示例代码。

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

AIDL简介

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

这里我们需要建立两个工程,一个作为客户端,另外一个作为服务端。

一、建立客户端的工程,结构如下:

这里写图片描述

首先新建一个package(com.zjt.myaidl)。在该package中新建一个名为IMyService.aidl的文件。如下:

package com.zjt.myaidl;
import com.zjt.myaidl.Person;
interface IMyService{
   List<Person> getPerson();
   void addPerson(in Person person);
}

说明:

  1. AIDL支持java基本类型如: int, long,double, char, boolean等。其他类型必须要用import 导入,即使是在同一个包中。比如本工程中IMyService和Person是在同一个包中。

  2. 另外,接口中的参数除了aidl支持的类型,其他类型必须标识其方向:到底是输入还是输出抑或两者兼之,用in,out或者inout来表示,上面的代码我们用in标记,因为它是输入型参数。

  3. 如果需要访问自定义对象,还需要建立对象的aidl文件,这里我们由于使用了自定义对象Person,所以还需建立一个Person.aidl文件。

由于使用了自定义对象Person,那么需要对该对象进行序列化。这里我们让Person 类实现Parcelable接口。

Person.java:

public class Person implements Parcelable {

    private String name ;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Person(String name,int age , String sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public Person(){

    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        Log.e("xxx", "writeToParcel");
        //这里字段写的顺序要和下面读的顺序要一致,从name、age到sex
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeString(sex);
    }


    public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {

        @Override
        public Person[] newArray(int size) {
            // TODO Auto-generated method stub
            return new Person[size];
        }

        @Override
        public Person createFromParcel(Parcel source) {
            // TODO Auto-generated method stub
            Person person = new Person();
            //这里字段读的顺序要和下面写的顺序要一致,从name、age到sex
            person.name = source.readString();
            person.age = source.readInt();
            person.sex = source.readString();
            return person;
        }
    };

}

Person.aidl文件很简单,如下所示,要注意的是 这里parcelable是个类型,首字母是小写的,和Parcelable接口不是一个东西。

package com.zjt.myaidl;
parcelable Person;

二、建立服务端的Service,MyService.java文件如下:

public class MyService extends Service{

    //private IBinder mBinder;

    private List<Person> mPersons = new ArrayList<Person>();

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return mBinder;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Person mPerson = new Person("zjt", 28, "male");
        mPersons.add(mPerson);
    }
    //在这里实现aidl中的抽象方法
    private final IMyService.Stub mBinder = new IMyService.Stub() {

        @Override
        public List<Person> getPerson() throws RemoteException {
            // TODO Auto-generated method stub
            synchronized (mPersons) {
                return mPersons;
            }

        }

        @Override
        public void addPerson(Person person) throws RemoteException {
            // TODO Auto-generated method stub
            synchronized (mPersons) {
                if(!mPersons.contains(person)){
                    mPersons.add(person);
                }
            }
        }
    };

三、在AndroidManifest.xml文件中声明Service:

 <service android:name="com.example.myaidlactivity.MyService"
     android:process=":remote"
     android:enabled="true">
     <intent-filter >
         <category              
         android:name="android.intent.category.DEFAULT"/>
        <action     
            android:name="com.example.myservice.action"/>
            </intent-filter>

        </service>

说明:上述的 是为了能让其他apk通过action来隐式启动bindService,通过隐式调用的方式来起activity或者service,需要把category设为default,这是因为,隐式调用的时候,intent中的category默认会被设置为default。

以上完成后,新建一个工程来充当客户端。

四、新建一个工程来充当客户端。
1.新建一个名为TestAidlClient的工程充当客户端。把上面的服务端中整个package(com.zjt.myaidl)copy到本项目的src目录下,

工程结构如下:

这里写图片描述

这个时候,客户端com.zjt.myaidl包是和服务端工程完全一样的。

MainActivity.java:

public class MainActivity extends Activity {

    private IMyService myService;
    private List<Person> mPersons = new  ArrayList<Person>();
    private Button bindService;

    private final static String SERVICE_ACTION = "com.example.myservice.action";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService = (Button) findViewById(R.id.bindService);
        bindService.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent mIntent = new Intent(SERVICE_ACTION);
                bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
            }
        });
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            myService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //通过服务端onBind方法返回的binder对象得到IMyService的实例,得到实例就可以调用它的方法了
            myService = IMyService.Stub.asInterface(service);
            try {
                //通过IMyService接口来添加Person对象
                myService.addPerson(new Person("wj", 26, "female"));
                mPersons = myService.getPerson();
                for(int i=0; i<mPersons.size();i++){
                    Person person = mPersons.get(i);
                    Log.e("----", "name = "+person.getName()+"\n age = "+person.getAge()+"\n sex = "+person.getSex());
                    Log.d("...", ".............");
                }


            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    };


}

运行结果如下:
这里写图片描述

可以看到我们通过aidl的方式获取到另一apk的数据。

源码下载地址:http://download.csdn.net/detail/zhujiangtaotaise/9384987

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值