AIDL详解

来源:互联网 发布:森田疗法 知乎 编辑:程序博客网 时间:2024/05/16 19:21

一、概述
AIDL是Android Interface Definition Language,即Android接口定义语言。设计这门语言的目的主要是为了是:进程间通信。在Android中,每一个进程都是单独的一个Dalvik VM实例,拥有自己独立的内存,存储数据,执行操作。AIDL就是负责定义一些两个进程间相互认可的通信规则,用来传输数据,沟通交流。
二、语法

  • 文件类型:用AIDL书写的文件后缀是.aidl,而不是.java。
  • 导包:使用AIDL只是的数据类型不需要导包,使用自己定义的实体类型,即使引用的实体与使用的类在同一个包下面,也要导报。列入demo中Course.java与CourseManager.aidl同在com.gyg.aidlclient下面,在CourseManager.aidl中使用Course.java也要import com.gyg.aidlclient.Course;(这个好像要手动导入,负责编译的时候会报错)。
  • 数据类型:默认支持的数据类型:
    *Java中的八种基本数据类型:byte,short,int,long,float,double,boolean,char。
    *String类型
    *CharSequence
    *List list中的所有元素必须AIDL支持的类型之一,或一个其它AIDL生成的接口,或定义的parcelable。支持泛型。
    *Map map中的所有元素必须是AIDL支持的类型之一,或一个其它AIDL生成的接口,或定义的parcelable。不支持泛型。
  • 定向tag
    *in 数据流向从客户端到服务端,服务端接收到客户端的一个完整对象,客户端接收到服务端一个空的对象。
    *out 数据流向从服务端到客户端,服务端接收到客户端的一个空对象,客户端接收到服务端一个完整对象。
    *inout 数据流向双向,服务端接收到客户端的一个完整对象,客户端接收到服务端的一个完整对象。
  • 两种.aidl
    * 定义parcelable对象,供其它aidl文件使用非默认的数据类型。例如demo中的Course.aidl。
    * 定义方法接口,用来完成跨进程数据通信的。例如demo中的CourseManager.aidl。
    三、示例代码

1、自定义实体类Course.java,继承自parcelable接口

public class Course implements Parcelable {    private String name;//课程名称    private double credit;//课程学分    private String teacher;//课程教师    public Course() {    }    public Course(String name, double credit, String teacher) {        this.name = name;        this.credit = credit;        this.teacher = teacher;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public double getCredit() {        return credit;    }    public void setCredit(double credit) {        this.credit = credit;    }    public String getTeacher() {        return teacher;    }    public void setTeacher(String teacher) {        this.teacher = teacher;    }    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeString(this.name);        dest.writeDouble(this.credit);        dest.writeString(this.teacher);    }    public void readFromParcel(Parcel dest) {        name = dest.readString();       credit=dest.readDouble();        teacher=dest.readString();    }    protected Course(Parcel in) {        this.name = in.readString();        this.credit = in.readDouble();        this.teacher = in.readString();    }    public static final Parcelable.Creator<Course> CREATOR = new Parcelable.Creator<Course>() {        @Override        public Course createFromParcel(Parcel source) {            return new Course(source);        }        @Override        public Course[] newArray(int size) {            return new Course[size];        }    };    @Override    public String toString() {        return "Course{" +                "name='" + name + '\'' +                ", credit=" + credit +                ", teacher='" + teacher + '\'' +                '}';    }}

2、定义Course.aidl,供其它aidl文件使用Course对象。

/**注意:Course.java和Course.aidl的包名应该是一样的。这里有两种方法:1.将Course.java放到与Course.aidl同一个包下,然后在module的build.gradle里面添加 sourceSets {        main {            java.srcDirs = ['src/main/java', 'src/main/aidl']        }    }    2.将Course.java放在java目录下与Course.aidl的同一目录名下。build.gradle不需要任何设置。*/package com.gyg.aidlclient;parcelable Course;

3.定义CourseManager.aidl,定义接口间通信的规则

// CourseManager.aidlpackage com.gyg.aidlclient;import com.gyg.aidlclient.Course;// Declare any non-default types here with import statementsinterface CourseManager {    Course getCourse();//从服务器获取一个Course对象    Course updateCourseIn(in Course course);//in方式传一个Course对象到服务器端,并接受服务器端返回的Course对象    Course updateCourseOut(out Course course);//out方式传一个Course对象到服务器端,并接受服务器端返回的Course对象    Course updateCourseInOut(inout Course course);//inout方式传一个Course对象到服务器端,并接受服务器端返回的Course对象}

3、将aidl目录的文件原封不懂的复制到服务器端下面,(服务器端aidl文件的包名要一致,否则会编译错误);
4、服务端编写AIDLService.java

package com.gyg.aidlserver;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.support.annotation.Nullable;import com.gyg.aidlclient.Course;import com.gyg.aidlclient.CourseManager;/** * Created by gyg on 2017/2/14. */public class AIDLService extends Service{    private final CourseManager.Stub mCourseManager=new CourseManager.Stub(){        @Override        public Course getCourse() throws RemoteException {            return new Course("Android高级开发",17.3,"Jack");//创建并返回一个Course对象给客户端,在客户端查看是否接受到该对象,接收到则表明两个进程间成功通信        }        /**         * in方式接受一个Course对象,并         * @param course         * @return         * @throws RemoteException         */        @Override        public Course updateCourseIn(Course course) throws RemoteException {            if (course==null){                course=new Course();            }            System.out.println("服务端In:"+course);            course.setCredit(233.3);            return course;        }        @Override        public Course updateCourseOut(Course course) throws RemoteException {            if (course==null){                course=new Course();            }            System.out.println("服务端Out:"+course);            course.setCredit(233.3);            return course;        }        @Override        public Course updateCourseInOut(Course course) throws RemoteException {            if (course==null){                course=new Course();            }            System.out.println("服务端InOut:"+course);            course.setCredit(177.77);            return course;        }    };    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mCourseManager;//返回mCourseManager给客户端,客户端利用mCourseManager与服务端进行通信    }}

5、AndroidManifest.xml中注册AIDLService.java

<!--注意android:exported="true"一定要添加,否则客户端链接不到Service-->        <service android:name=".AIDLService"            android:exported="true"            >            <intent-filter>                <action android:name="com.gyg.aidl"/>                <category android:name="android.intent.category.DEFAULT"/>            </intent-filter>        </service>

6、客户端编写测试代码:

package com.gyg.aidlclient;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.TextView;public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private CourseManager mCourseManager;    Course originCourse;//服务器端返回的Course对象    private boolean mBound=false;//记录service是否连接    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.updateIn).setOnClickListener(this);        findViewById(R.id.updateOut).setOnClickListener(this);        findViewById(R.id.updateInOut).setOnClickListener(this);    }    @Override    protected void onStart() {        super.onStart();        if (!mBound){            connectService();//绑定service        }    }    @Override    protected void onStop() {        super.onStop();        if (mBound=true){            unbindService(mServiceConnection);//解绑service        }    }    private ServiceConnection mServiceConnection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            mCourseManager=CourseManager.Stub.asInterface(iBinder);            Log.d(getLocalClassName(),"Service Connected");            if (mCourseManager!=null){                try {                    originCourse=mCourseManager.getCourse();//获取服务器返回的Course对象                    ((TextView)findViewById(R.id.originTxt)).setText(originCourse.toString());//显示服务器返回的对象数据                } catch (RemoteException e) {                    e.printStackTrace();                }            }            mBound=true;        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            Log.d(getLocalClassName(),"Service UnConnected");            mBound=false;        }    };    //隐式链接AIDLService    private void connectService(){        Intent intent=new Intent();        intent.setAction("com.gyg.aidl");        intent.setPackage("com.gyg.aidlserver");        bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);    }    @Override    public void onClick(View view) {        switch (view.getId()){            case R.id.updateIn://测试in方式返回的数据                if (mCourseManager!=null){                    try {                        mCourseManager.updateCourseIn(originCourse);                        ((TextView)findViewById(R.id.inTxt)).setText("定向IN:"+originCourse.toString());//显示定向in后originCourse数据                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }                break;            case R.id.updateOut://测试out方式返回的数据                if (mCourseManager!=null){                    try {                        mCourseManager.updateCourseOut(originCourse);                        ((TextView)findViewById(R.id.outTxt)).setText("定向OUT:"+originCourse.toString());//显示定向out后originCourse数据                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }                break;            case R.id.updateInOut:                if (mCourseManager!=null){//测试inout方式返回的数据                    try {                        mCourseManager.updateCourseInOut(originCourse);                        ((TextView)findViewById(R.id.inoutTxt)).setText("定向INOUT:"+originCourse.toString());//显示定向inout后originCourse数据                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }                break;        }    }}

四、测试结果分析
1.首先运行AIDLServer,再运行AIDLClient,成功后运行结果如下:
这里写图片描述
说明AIDLClient与AIDLServer通信成功,成功获得到AIDLServer传过来的数据
2.点击UPDATEIN按钮,服务器端输出结果:
这里写图片描述
服务器接收到客户端的一个完整对象
客户端输出结果:
这里写图片描述
服务器端的数据对客户端的数据没有影响
3.点击UPDATEOUT,服务器端结果:
这里写图片描述
服务器端接收到客户端的一个空对象
客户端结果:
这里写图片描述
客户端因为服务器端的数据的改变而更改了。
4.点击UPDATEINOUT按钮:
服务器端结果:
这里写图片描述
客户端接收到服务端的完整对象
客户端结果:
这里写图片描述
客户端因为服务端数据的变化而发生了更改。
五、demo

0 0
原创粉丝点击