Android开发经验谈Binder机制

Android进程间通讯(一)Binder介绍及AIDL的具体使

2020-04-01  本文已影响0人  程序员三千_

Android进程间通讯(一)Binder介绍及AIDL的具体使用
Android进程间通讯(二)AIDL、Binder源码分析

首先我们要明白几个概念

image.png

Binder是Android系统进程间通信(IPC)方式之一,但是为什么Android不使用Linux本生具有的IPC方式?

Binder优点

AIDL是什么?

AIDL是Android为了方便使用Binder机制出现的接口定义语言,只是Android中众多进程间通讯方式中的一种方式。其实不用这个也能达到目的,但是用这个就简化了操作。只要按照规范写一个.aidl文件,系统会帮助自动创建一个与interface同名的.java文件,里面已经帮我们自动写好一堆标准代码,这些标准化的东西,用模板自动生成即可,让开发者尽量关注功能实现上。

通俗的来讲,AIDL的作用就是,让你可以在自己的APP里绑定另一个APP的service,这样就实现了两个app间的交互,而这两个app的交互的规则具体表现就是通过.aidl文件里定义的接口里面的一些方法。

IPC(Inter-Process Communication:进程间通信。
AIDL(Android Interface definition language):Android接口定义语言。
Binder :IPC的通讯机制。

AIDL使用例子

因为是两个app间的数据交互,我这里新建了两个工程,一个代表客户端一个代表服务端,客户端和服务端都存在一个ILeoAidl接口

package com.xx.leo_service;

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

import com.xx.leo_service.Person;

interface ILeoAidl {
    void addPerson(in Person person);

    List<Person> getPersonList();
}
// Person.aidl
package com.xx.leo_service;

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

parcelable Person;
package com.xx.leo_service;

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable {

    private String name;
    private int grade;

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

    protected Person(Parcel in) {
        this.name = in.readString();
        this.grade = in.readInt();
    }

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

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

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

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }
}


//绑定服务
 private void bindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.xx.leo_service", "com.xx.leo_service.LeoAidlService"));
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }


    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: success");
            iLeoAidl = ILeoAidl.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected: success");
            iLeoAidl = null;
        }
    };

   private void initView() {
        btn = (Button) findViewById(R.id.but_click);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    iLeoAidl.addPerson(new Person("小三爷", 3));
                    List<Person> persons = iLeoAidl.getPersonList();
                    Log.e(TAG, persons.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

主要就是绑定aidl服务,连接服务获取aidl对象,然后通过一个按钮,调用aidl对象的addPerson方法添加一个person,然后通过iLeoAidl接口获取list数组里的值和list的长度,并且打印日志

服务端主要是新建一个service,并且启动这个service就ok

//清单文件里记得声明下这个服务
  <service
            android:name=".LeoAidlService"
            android:exported="true" />
//1、新建服务
public class LeoAidlService extends Service {

    private ArrayList<Person> persons;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        persons = new ArrayList<>();
        Log.e("LeoAidlService", "success onBind");
        return iBinder;
    }

    private IBinder iBinder = new ILeoAidl.Stub() {
        @Override
        public void addPerson(Person person) throws RemoteException {
            persons.add(person);
        }

        @Override
        public List<Person> getPersonList() throws RemoteException {
            return persons;
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("LeoAidlService", "onCreate: success");
    }
}
//2、启动服务
startService(new Intent(this, LeoAidlService.class));

image.png

好,我们现在根据代码再分析下流程
1、服务端和客户端都定义一个aidl接口,接口里有增加和显示list的方法
2、客户端点击按钮,调用aidl的接口方法,往list里面增加数组,然后日志打印数据

结论

运行代码,第一次先把客户端和服务端app都运行起来,

那么问题来了,1、客户端是怎么获取这个遥控器的呢?2、这个遥控器又是怎么调用到服务端代码的呢?3、就算把服务端app杀死了,客户端为什么还能调用到服务端的代码?我们直接进入下一篇文章:Android进程间通讯(二)AIDL源码分析

上一篇 下一篇

猜你喜欢

热点阅读