Android AIDL 学习记录

AIDL全程为 Android Interface Definition Language 即 android接口定义语言  能够进行进程间的通讯

通讯时默认支持的数据类型如下:

(1)Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。

(2)String 类型和CharSequence类型。

(3)List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是由parcelable进行序列化的对象。List可以使用泛型。

(4)Map类型:Map中的所有元素和list所支持的一致,但是Map是不支持泛型的。

使用AIDL也可以传递对象,但是对象必须经过parcelable进行序列化才可以使用,序列化形式如下:

public class Bean_Data implements Parcelable {
    private String data;

    public Bean_Data(){

    }

    protected Bean_Data(Parcel in) {
        data = in.readString();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public Bean_Data createFromParcel(Parcel in) {
            return new Bean_Data(in);
        }

        @Override
        public Bean_Data[] newArray(int size) {
            return new Bean_Data[size];
        }
    };

    public String getData() {
        //如果是String类型,那么判断是否为空,为空返回"",否则返回字段值本身
        return data == null ? "" : data;
    }

    public void setData(String data) {
        this.data = data;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(data);
    }
    /**
     * 参数是一个Parcel,用它来存储与传输数据
     * @param dest
     */
    public void readFromParcel(Parcel dest) {
        //注意,此处的读值顺序应当是和writeToParcel()方法中一致的
        data = dest.readString();
    }

}

readFromParcel方法为人为记性添加,其余方法除get和set方法外都可以通过编译器进行自动添加

传递序列化的对象时 应在定义接口方法的时候使用定向tag,定向tag的使用方法如下:

AIDL中的定向 tag 表示了在跨进程通信中数据的流向,其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。其中,数据流向是针对在客户端中的那个传入方法的对象而言的。in 为定向 tag 的话表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;out 的话表现为服务端将会接收到那个对象的的空对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;inout 为定向 tag 的情况下,服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。

 

服务端的AIDL如下:

Android AIDL 学习记录_第1张图片

Bean_Data.aidl:

// IBean_Data.aidl
package com.fei.aidldemo.bean;
// Declare any non-default types here with import statements
parcelable Bean_Data;

Aidl_CommunionInterface.aidl:

// Aidl_CommunionInterface.aidl
package com.fei.aidldemo;
import com.fei.aidldemo.bean.Bean_Data;
// Declare any non-default types here with import statements

interface Aidl_CommunionInterface {
    void sendMsg(in Bean_Data msg);
    String accpetMsg(Aidl_CommunionInterface callBack);
}

之后进行Sync  AS将会在如下目录产生一个java文件,此文件将会在客户端使用,目录如下:

Android AIDL 学习记录_第2张图片

之后,在服务端需要编写一个Service,找服务中进行数据的交换传递的逻辑,如下:

public class Service_Aidl extends Service {

    private Aidl_CommunionInterface callBack;
    private int num = 0;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mAidl_communionInterface;
    }

    private Aidl_CommunionInterface.Stub mAidl_communionInterface = new Aidl_CommunionInterface.Stub() {

        @Override
        public void sendMsg(Bean_Data msg) throws RemoteException {

        }

        @Override
        public String accpetMsg(Aidl_CommunionInterface mCallBack) throws RemoteException {
            callBack = mCallBack;
            if(null == callBack){
                return "失败";
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Bean_Data data = new Bean_Data();
                        data.setData(num+"");
                        try {
                            callBack.sendMsg(data);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        num ++;
                    }
                }
            }).start();
            return "这是AIDL传递过来的数据";
        }
    };

}

此处为了偷懒,数据传递,以及服务端主动发送数据的回调使用同一个AIDL实现,仅仅使用不同方法进行区分,sendMsg方法为每经过1S主动向客户端上报数据,数据为已经序列化的对象,accpetMsg方法为客户端主动查询的接口

下面为客户端的内容:

首先应该先将上面服务端生成的.java文件复制到客户端的工程中,主要路径应该与其在服务端的路径一致

客户端路径如下:

Android AIDL 学习记录_第3张图片

 

MainActivity.java代码如下:

public class MainActivity extends AppCompatActivity {

    private TextView main_get_tv;
    private Button main_get_bt;

    private Aidl_CommunionInterface mAidl_communionInterface;

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

        initBindService();

        initView();


    }


    private void initBindService(){
        Intent intent = new Intent();
        intent.setAction("com.fei.aidl");
        intent.setPackage("com.fei.aidldemo");
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }


    private void  initView(){
        main_get_tv = findViewById(R.id.main_get_tv);
        main_get_bt = findViewById(R.id.main_get_bt);

        main_get_bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    main_get_tv.setText( mAidl_communionInterface.accpetMsg(new Aidl_CommunionInterface.Stub() {

                        @Override
                        public void sendMsg(final Bean_Data msg) throws RemoteException {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    main_get_tv.setText(msg.getData());
                                }
                            });
                        }

                        @Override
                        public String accpetMsg(Aidl_CommunionInterface callBack) throws RemoteException {
                            return null;
                        }
                    }));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }



    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mAidl_communionInterface = Aidl_CommunionInterface.Stub.asInterface(iBinder);
            main_get_tv.setText("连接成功");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onStop() {
        super.onStop();
        if(null != mServiceConnection){
            unbindService(mServiceConnection);
        }
    }
}

需注意的是在BingService时,action和package的值应该与服务端的Service在清单文件中的值一致

Android AIDL 学习记录_第4张图片

服务端的Service在清单文件:

Android AIDL 学习记录_第5张图片

运行,安装,之后先打开服务端,按Home键退出,在打开客户端,点击获取数据按钮,可以正常获取数据

上述代码中包含基础类型数据的传递,服务端的主动下发数据,以及非基础类型数据(序列化的对象)的传递

服务端和客户端的下载地址:https://download.csdn.net/download/u011685953/11103408

AIDLDemo为服务端      AIDLDemoGet为客户端

你可能感兴趣的:(公司项目所用,android,AIDL,IPC,进程间通讯)