Android中的IPC-(AIDL)

aidl :Android Interface Definition Language,即Android接口定义语言

首先我们服务端需要创建一个Service来监听客户端的连接,然后创建一个aidl文件,将暴露给客户端的接口在这个aidl中声明,最后在Service中实现这些接口.

在客户端就是bind服务端的Servcie,然后将返回的Binder对象转换为aidl接口的类型,然后就能调用aidl的方法了.

AIDL中支持的数据类型:

  1. Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)

  2. String和CharSequence

  3. List:在List中的所有元素必须以上列表中支持的数据类型之一,或者其他 AIDL 生成的接口或自定义序列化的类型之一。可选择将List用作“通用”类(例如,List)。虽然方法生成使用的是List接口,但实际上其他端接收到的类总是ArrayList。

  4. Map:在Map中的所有元素必须以上列表中支持的数据类型之一,或者其他 AIDL 生成的接口或自定义序列化的类型之一。不支持通用 Map(如 Map 形式的 Map)。虽然方法生成使用的是Map接口,但实际上其他端接收到的类总是HashMap。

  5. Parcelable :实现了Parcelable接口的对象

  6. AIDL:所有的AIDL接口本身也可以在AIDL中使用

  1. AIDL中除了基本数据类型,其他类型的参数都必须标上方向in,out ,inout
  2. AIDL中只支持方法,不支持声明静态常量

接下来我们就一步步的来使用AIDL

  1. 准备工作(创建Picture类)
public class Picture implements Parcelable {

    public int id;
    public String url;
    public String name;

    public Picture(int id, String url, String name) {
        this.id = id;
        this.url = url;
        this.name = name;
    }

    protected Picture(Parcel in) {
        this.id = in.readInt();
        this.url = in.readString();
        this.name = in.readString();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.url);
        dest.writeString(this.name);
    }


    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public Picture createFromParcel(Parcel source) {
            return new Picture(source);
        }

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

    @Override
    public String toString() {
        return "Picture{" +
                "id=" + id +
                ", url='" + url + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
  1. 第一步创建aidl文件
// IPictureManager.aidl
package com.wsw.bindertest;

// Declare any non-default types here with import statements
import com.wsw.bindertest.picture.Picture;

interface IPictureManager {

    List getPictures();

    void addPicture(in Picture picture);
}

这里需要注意的是,AIDL中使用到了的自定义类,必须为实现了Parcelable接口的类,如这里的:Picture

在创建好文件后,写入需要调用的方法,之后进行build,会发现系统自动生成了一个java文件,路径为:app\build\generated\source\aidl\debug\com\wsw\bindertest\IPictureManager.java

  1. 第二步服务的实现
public class PictureService extends Service {
    private static final String TAG = "PictureService";

    private CopyOnWriteArrayList mPictureList = new CopyOnWriteArrayList<>();

    IPictureManager mBinder = new IPictureManager.Stub() {
        @Override
        public List getPictures() throws RemoteException {
            SystemClock.sleep(5000);
            Log.i(TAG, "getPictures: "+Thread.currentThread().getName());
            return mPictureList;
        }

        @Override
        public void addPicture(Picture picture) throws RemoteException {
            Log.i(TAG, "addPicture: "+Thread.currentThread().getName());
            mPictureList.add(picture);
        }
    };

    @Override
    public void onCreate() {
        mPictureList.add(new Picture(1, "url1", "四川"));
        mPictureList.add(new Picture(1, "url1", "湖北"));
        super.onCreate();
    }

    public PictureService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder.asBinder();
    }

}

这里在xml中需要注册此服务,同时因为是模拟不同进程之间的通信,所以需要指定android:process属性,让次service与activity运行于不同的进程



  1. 第三步客户端的实现
public class PictureManagerActivity extends AppCompatActivity {

    private IPictureManager remote = null;

    private static final String TAG = "PictureManagerActivity";

    ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(TAG, "onServiceConnected: " + Thread.currentThread().getName());
            IPictureManager pictureManager = IPictureManager.Stub.asInterface(service);
            try {
                remote = pictureManager;
                List pictureList = pictureManager.getPictures();
                Log.d(TAG, "pictureList" + pictureList);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_picture_manager);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    remote.addPicture(new Picture(3, "11", "西藏"));
                    List lists = remote.getPictures();
                    Log.d(TAG, "new Picture List is:" + lists);

                } catch (RemoteException e) {
                    e.printStackTrace();
                }


            }
        });

        Intent intent = new Intent(this, PictureService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

}

这样一个简单的aidl的使用就完成了.

你可能感兴趣的:(Android中的IPC-(AIDL))