进程间通信之 -- Messenger

网上关于Messenger的文章很多,但是通俗易懂的少,这里简单介绍一下我的理解。

一言以蔽之即:

消息Message 可以 绑定 信使Messenger


触发流程:

A 收到 一个消息Messge,里面有个信使 Messenger_B,

那么这时候 A 就可以通过 Messenger_B.send(msg); 将消息msg发给 B,

B 内直接回调 Messenger_B 所绑定的 handler。


举例:

应用A Client 端

应用 B Service 端

假设A 已经拿到 B 的 Messenger,即 serviceMessenger 。

具体如何拿到后面补充。

Client端代码

Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("电影", "科幻电影");
message.setData(bundle);
message.what = 1;
//最重要的一步,将clientMessenger绑定在消息内,发给服务端,这样服务端可以用 clientMessenger 再发送消息回来。
message.replyTo = clientMessenger;

try {
    serviceMessenger.send(message);
} catch (RemoteException e) {
    e.printStackTrace();
}
记住这里最重要的一步就是 设置 replyTo,这样当服务端收到你的消息后,可以再使用你的信使把消息给你发回来

Service端代码

private static class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {

        switch (msg.what) {
            case 1:
                Bundle data = msg.getData();
                String s = data.getString("电影","辣鸡");
                Log.i("服务端", s);

                Message message = new Message();
                Bundle bundle = new Bundle();
                bundle.putString("晚餐","服务端给客户端发来了晚餐消息");
                message.what = 2;
                message.setData(bundle);

                try {
                    //看这里,最重要的一步,使用消息msg内所附带的信使,这里也就是 clientMessenger,再把消息发送回去
                    msg.replyTo.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

                break;
            default:
                super.handleMessage(msg);
        }
    }
}
结果 

客户端绑定服务端,拿到服务端信使,发送了一条消息 ClientMsg 过去,消息内数据为 “科幻电影”

服务端拿到了数据,并使用 ClientMsg 内 所绑定的信使(即客户端的信使),再发送一条消息回去,信息内容为 “服务端给客户端发来了晚餐消息”。

01-12 18:17:23.461 14704-14704/com.example.yanlong.client I/客户端: 绑定成功
01-12 18:17:23.461 14704-14704/com.example.yanlong.client I/客户端: 服务端给客户端发来了晚餐消息

01-12 18:17:23.461 14500-14500/com.example.yanlong.service I/服务端: 开始创建 onCreate
01-12 18:17:23.461 14500-14500/com.example.yanlong.service I/服务端: onBind
01-12 18:17:23.461 14500-14500/com.example.yanlong.service I/服务端: 科幻电影


如何在客户端拿到服务端的信使 Messenger

很简单,就像平常开启服务差不多。这里我将代码贴出。

代码里没有去操作关闭服务,以及使用boolean 判断是否绑定成功。各位后期增加。

Client

package com.example.yanlong.client;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
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.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private Messenger serviceMessenger;

    private static class ClientHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 2:
                    Bundle data = msg.getData();
                    String c = data.getString("晚餐");
                    Log.i("客户端", "" + c);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private Messenger clientMessenger = new Messenger(new ClientHandler());


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = (TextView) findViewById(R.id.textView);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService();
            }
        });

    }

    private ServiceConnection sc = new ServiceConnection() {


        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("客户端", "绑定成功");

            //重要,这里是获取服务端信使
            serviceMessenger = new Messenger(service);

            Message message = Message.obtain();
            Bundle bundle = new Bundle();
            bundle.putString("电影", "科幻电影");
            message.setData(bundle);
            message.what = 1;

            //最重要的一步,将clientMessenger绑定在消息内,发给服务端,这样服务端可以用 clientMessenger 再发送消息回来。
            message.replyTo = clientMessenger;

            try {
                serviceMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private void bindService() {
        Intent intent = new Intent();
        intent.setPackage("com.example.yanlong.service");
        intent.setAction("comxxxxx");
        bindService(intent, sc, BIND_AUTO_CREATE);
    }

}

Service端

package com.example.yanlong.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
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.annotation.Nullable;
import android.util.Log;

/**
 * 项目名称:Service
 * 类名称  :com.example.yanlong.service
 * 作者    :高延荣
 * 创建时间:2018/1/12
 * 类描述  :
 */
public class MyService extends Service {

    private static class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 1:
                    Bundle data = msg.getData();
                    String s = data.getString("电影","辣鸡");
                    Log.i("服务端", s);

                    Message message = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("晚餐","服务端给客户端发来了晚餐消息");
                    message.what = 2;
                    message.setData(bundle);

                    try {
                        //看这里,最重要的一步,使用消息msg内所附带的信使,这里也就是 clientMessenger,再把消息发送回去
                        msg.replyTo.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    Messenger messenger = new Messenger(new MyHandler());

    @Override
    public void onCreate() {
        Log.i("服务端", "开始创建 onCreate");
        super.onCreate();

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("服务端", "onBind");
        return messenger.getBinder();
    }

    private class MyBinder extends Binder {
        public void doSome() {
            Log.i("服务端", "已经接收到您的服务请求");
        }
    }

}
服务端清单配置

<service android:name=".MyService">
    <intent-filter>
        <action android:name="comxxxxx" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>




猜你喜欢

转载自blog.csdn.net/qq_26030147/article/details/79046808
今日推荐