天天看点

Android进程间通讯之messenger

平时一说进程间通讯(IPC),大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯。它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是很爽。

此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。

与 AIDL 比较:

  当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。

  对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

接下来看下怎么用:

服务端:

1.创建一个handler对象,并实现hanlemessage方法,用于接收来自客户端的消息,并作处理

2.创建一个messenger(送信人),封装handler 

3.用messenger的getBinder()方法获取一个IBinder对象,通过onBind返回给客户端

客户端:

1.在activity中绑定服务

2.创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化 

3.使用Messenger向服务端发送消息

4.解绑服务

5.服务端中在 handleMessage() 方法中接收每个 Message

这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message 对象)是服务在其 Handler 中接收的。

上面实现的仅仅是单向通信,即客户端给服务端发送消息,如果我需要服务端给客户端发送消息又该怎样做呢?

其实,这也是很容易实现的,下面就让我们接着上面的步骤来实现双向通信吧

1.在客户端中创建一个Handler对象,用于处理服务端发过来的消息

2.创建一个客户端自己的messenger对象,并封装handler。

3.将客户端的Messenger对象赋给待发送的Message对象的replyTo字段

4.在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息

这样就实现了客户端和服务端的双向通信了。

注意:注:Service在声明时必须对外开放,即android:exported="true"

其实messenger底层也是AIDL。客户端和服务端通讯,就是普通的AIDL,客户端实例化stub之后,通过stub的send方法把消息发到服务端。服务端和客户端通讯:服务端通过解析message的replyto,获得客户端的stub,然后通过send方法发送到客户端。

客户端:

package com.example.ipc_messenger;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity1";
    private boolean mBond;
    private Messenger serverMessenger;
    private MyConn conn;
    //在客户端中创建一个Handler对象,用于处理服务端发过来的消息

    private Messenger mMessenger = new Messenger(new Handler(){
        @Override
        public void handleMessage(Message msg) {
            Toast.makeText(getApplicationContext(),"收到客户端的消息,内容是:"+msg.arg1,Toast.LENGTH_SHORT).show();
            super.handleMessage(msg);
        }
    });

    private class MyConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //连接成功
            serverMessenger = new Messenger(service);
            Log.i("Main", "服务连接成功");
            mBond = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            serverMessenger = null;
            mBond = false;
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定服务
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.example.ipc_messenger", "com.example.ipc_messenger.MyService"));
        conn = new MyConn();
        bindService(intent, conn, BIND_AUTO_CREATE);
        Button button = (Button) findViewById(R.id.bt1);
        //客户端给服务器发消息
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message toServiceMessage = Message.obtain();
                toServiceMessage.what = 1;
                toServiceMessage.arg1 = 12345;
                try {
                    //将客户端的Messenger对象赋给待发送的Message对象的replyTo字段
                    toServiceMessage.replyTo = mMessenger;
                    serverMessenger.send(toServiceMessage);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        if (mBond) {
            unbindService(conn);
        }
        super.onDestroy();
    }
}
           

服务端:

package com.example.ipc_messenger;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {
    private static final String TAG = "MyService1";
    private static final int CODE = 1;
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        Log.d(TAG, "onBind: ");
        return mMessenger.getBinder();
    }
    //创建一个送信人,封装handler
    private Messenger mMessenger = new Messenger(new serviceHandler());

    public class serviceHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Message toClientMessage = Message.obtain();
            switch (msg.what) {
                case CODE:
                    //接收来自客户端的消息,并作处理
                    int arg = msg.arg1;
                    Log.d(TAG, "handleMessage: msg.arg1="+msg.arg1);
                    Toast.makeText(getApplicationContext(),"收到客户端的消息,内容是:"+arg+"" , Toast.LENGTH_SHORT).show();
                    //在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息
                    toClientMessage.arg1 = 1111111111;
                    try {
                        //回复客户端消息
                        msg.replyTo.send(toClientMessage);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
            }
            super.handleMessage(msg);
        }
    }
}