AIDL详解

一、概述
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.aidl
package com.gyg.aidlclient;
import com.gyg.aidlclient.Course;

// Declare any non-default types here with import statements

interface 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值