Android Service详解(七)---绑定服务BoundService详解之Messenger双向通信的实现

作者: SuperBig 发布时间: 2019-09-12 浏览: 200 次 编辑

这是第七篇文章主要讲的是BoundService中用Messenger实现IPC。

前三篇文章对扩展Binder类和AIDL进行了说明,绑定服务一般通过AIDL和Messenger来实现IPC


一、概述


Messenger实现IPC通信,底层也是使用了AIDL方式。和AIDL方式不同的是,  Messenger方式是利用Handler形式处理,因此,它是线程安全的,这也表示它不支持并发处理;而AIDL方式是非线程安全的,支持并发处理,因此,我们使用,AIDL方式时需要保证代码的线程安全。

大部分情况下, 我们应用中不需要并发处理。 因此, 我们通常只需要使用Messenger方式。

思想:在进程A中创建一个Message,将这个Message对象通过Messenger.send(message)方法传递到进程B(当然, Message对象本身是无法被传递到进程B的, send(message)方法会使用一个Parcel对象对Message对象编集,再将Parcel对象传递到进程B中,然后解编集,得到一个和进程,A中Message对象内容一样的对象) ,再把Message对象加入到进程B的消息队列里, Handler会去处理它。


二、具体步骤,双向通信的实现

1.首先创建一个Service服务,并实现一个 Handler,由其接收来自客户端的每个调用的回调

(这个是接收时的代码)

class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_SAY_HELLO:
                Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                System.out.println(msg.getData().getString("info"));
                
                break;
            default:
                super.handleMessage(msg);
        }
    }
}


(实现双向通信的代码,接收后发送给客户端)

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    System.out.println(msg.getData().getString("info"));
                    //实现双向通讯
                    Messenger client = msg.replyTo;
                    Message replyMessage = Message.obtain(null, MSG_SAY_HELLO);
                    for(int i = 0;i<20;i++){
                        try {
                            Thread.sleep(500);
                            Bundle bundle = new Bundle();
                            bundle.putString("reply", "嗯嗯,我已经收到你的第"+i+"条信息,稍后回复你。");
                            replyMessage.setData(bundle);
                            try {
                                client.send(replyMessage);
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
 
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }


2.Handler 用于创建 Messenger 对象(对 Handler 的引用)

final Messenger mMessenger = new Messenger(new IncomingHandler());

3.Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端

 @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }

4.上述完整代码

public class MessengerService extends Service {
    /** Command to the service to display a message */
    static final int MSG_SAY_HELLO = 1;
 
    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    System.out.println(msg.getData().getString("info"));
                    //实现双向通讯
                    Messenger client = msg.replyTo;
                    Message replyMessage = Message.obtain(null, MSG_SAY_HELLO);
                    for(int i = 0;i<20;i++){
                        try {
                            Thread.sleep(500);
                            Bundle bundle = new Bundle();
                            bundle.putString("reply", "嗯嗯,我已经收到你的第"+i+"条信息,稍后回复你。");
                            replyMessage.setData(bundle);
                            try {
                                client.send(replyMessage);
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
 
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
 
    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());
 
    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

5.客户端使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用后者将 Message 对象发送给服务

(1)定义一个Messenger对象,Messenger mService = null;并在绑定成功后实例化

public void onServiceConnected(ComponentName className, IBinder service) {
    // This is called when the connection with the service has been
    // established, giving us the object we can use to
    // interact with the service.  We are communicating with the
    // service using a Messenger, so here we get a client-side
    // representation of that from the raw IBinder object.
    mService = new Messenger(service);
    mBound = true;
}

(2)声明一个Handler用来处理服务端的数据

    private class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MessengerService.MSG_SAY_HELLO:
                    System.out.println("receive from Service:" + msg.getData().get("reply"));
                    TextView textView = new TextView(getApplicationContext());
                    textView.setTextColor(Color.BLACK);
                    textView.setText("receive from Service:" + msg.getData().get("reply"));
                    linearLayout.addView(textView);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

(3)声明一个Messenger对象

public void sayHello(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putString("info","呵呵哒");
        msg.setData(bundle);
        msg.replyTo = mGetReplyMessenger;
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }


并用msg.replyTo得到Messenger实例


至此绑定服务就基本结束了。

附上源码:源码


Android Service详解系列

1,Android Service详解(一)---概述4,Android Service详解(四)---绑定服务BoundService详解之扩展Binder类7,Android Service详解(七)---绑定服务BoundService详解之Messenger双向通信的实现
2,Android Service详解(二)---StartService5,Android Service详解(五)---绑定服务BoundService详解之AIDL的使用8,Android Service详解(八)---前台服务详解
3,Android Service详解(三)---IntentService6,Android Service详解(六)---绑定服务BoundService详解之AIDL的自定义属性使用



————————————————

原文链接:https://blog.csdn.net/superbiglw/article/details/53158164