Android 进程间通信之AIDL和Messenger

AIDL:Android Interface Definition Language,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。
ICP:Interprocess Communication ,内部进程通信。

使用:
1、先创建一个aidl文件,aidl文件的定义和java代码类似,但是!它可以引用其它aidl文件中定义的接口和类,但是不能引用自定义的java类文件中定义的接口和类,要引用自定义的接口或类,需要为此类也定义一个对应的aidl文件,并且此类要实现Parcelable接口,同时aidl文件和类文件必须要在相同包下进行声明;Android包含了aidl编译器,当定义好一个aidl文件的时候,会自动编译生成一个java文件,此文件保存在gen目录之下。

在这个项目中,定义了两个aidl文件,其中Person实现了接口Parcelable,下面是这两个aidl文件的定义:

Person.aidl 

{
  parcelable Person;
}

IAIDLServerService.aidl

{
  package com.webview;
  import com.webview.Person;// 引用上面的Person.aidl

  interface IAIDLServerService{
    String sayHello();
    Person getPerson();
  }
}

2、编写一个Service实现定义aidl接口中的内部抽象类Stub,Stub继承自Binder,并继承我们在aidl文件中定义的接口,我们需要实现这些方法。Stub中文意思存根,Stub对象是在服务端进程中被调用,即服务端进程。

在客户端调用服务端定义的aidl接口对象,实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时需要一个ServiceConnection对象,此对象其实就是用来在客户端绑定Service时接收Service返回的IBinder对象。

||public static abstract class Stub extends android.os.Binder implements com.webview.IAIDLServerService

public class AIDLServerService extends Service{

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
    
    private IAIDLServerService.Stub binder = new Stub() {
        @Override
        public String sayHello() throws RemoteException {
            return "Hello AIDL";
        }
        
        @Override
        public Person getPerson() throws RemoteException {
            Person person = new Person();
            person.setName("Livingstone");
            person.setAge(22);
            return person;
        }
    };
}

3、在服务端注册Service,将如下代码添加进Application节点之下!

<service android:name="com.webview.AIDLServerService" 
  android:process=":remote"> 
  <intent-filter> 
    <action android:name="com.webview.IAIDLServerService"></action> 
  </intent-filter> 
</service>

至此,服务端进程定义已经完成!

4、编写客户端,注意需要在客户端存一个服务端实现了的aidl接口描述文件,客户端只是使用该aidl接口,获取服务端的aidl对象(IAIDLServerService.Stub.asInterface(service))之后就可以调用接口的相关方法,而对象的方法的调用不是在客户端执行,而是在服务端执行。

public class MainActivity extends Activity {

    private Button btn;
    private IAIDLServerService aidlService = null;

    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            aidlService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            aidlService = IAIDLServerService.Stub.asInterface(service);
            try {
                aidlService.doFunction();// 执行接口定义的相关方法
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    };

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

        btn = (Button) findViewById(R.id.button);
        tv = (TextView) findViewById(R.id.textview);
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent service = new Intent("com.webview.IAIDLServerService");
                bindService(service, conn, BIND_AUTO_CREATE);// 绑定服务
            }
        });
    }
}

 客户端目录结构:

Messenger:

它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。
1.Service实现Handler接口用于接客户端的请求
2.Handler是要用于创建一个Messenger对象,这个对象要引用此Handler
3.Messenger创建一个IBinder,并且在Service的onBind()方法中返回给客户端
4.客户端用服务端返回的IBider对象实例化一个Messenger,此Messenger用于发送Message到Service服务端
5.服务端接收每一个Message,并且在Handler中对消息进行处理-->handleMessage()
6.如果需要服务端进行用户请求响应,需要在发送消息到服务端的时候,让Message引用客户端的Messenger对象(Handler.replyTo=Messenger),然后再调用Messenger的send()方法。这样服务端接收到消息的同时也得到了客户端的Messenger对象,服务端就可以通过客户端的Messenger对象向客户端发送消息。

这种方法,没有用于供客户端调用的方法,而是客户端发送消息到服务端,服务端接到消息后对消息进行相应的处理!

public class MSGService extends Service {
    Messenger mMessenger = new Messenger(new myHandler());
    class myHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case 1:
                Toast.makeText(getApplicationContext(), "Hello", 1).show();
                break;
            }
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
}
public class MainActivity extends Activity {
    Messenger mService = null;
    boolean bound = false;
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent();
        intent.setClassName("com.broadlistener", "com.broadlistener.MSGService");
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);    
            bound = true;
        }
    };
    public void click(View v) {
        if (bound) {
            Message msg = Message.obtain(null, 1, 0, 0);
            try {
                msg.replyTo = mService;// [6]
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
原文地址:https://www.cnblogs.com/a284628487/p/3024983.html