Android Messenger初探

1. 背景

最近在看任玉刚老师的《Android开发艺术探索》,看到了 Messenger,觉得挺有意思的,写个 Demo 练习一下,同时根据 Messenger 可以延伸到其他知识点,比如Android的Binder通信机制,AIDL等知识点,本文算是 Messenger 初探。

1.1 Messenger 介绍

首先肯定要看一下官方对于 Messenger 的介绍。

/**
 * 引用 Handler, 可以用其来发送 Message 信息。
 * 允许跨进程来实现基于信息的通讯,通过在一个进程中创建一个 Messenger 对象,并且关联一个 Handler 对象,然后将消息传递给另外一个进程。
 * 注意:其实现只是对 Binder 一个简单的包装,用于执行通信。这意味着从语义上来说:
 * 这个类不影响进程的生命周期管理,如果的进程因为任何原因离开,连接将中断,等等,你必须使用一些更高级的组件来告诉系统您的流程需要继续运行。
 */
public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

     /**
     * 创建一个指定(关联)了一个 Handler 对象的 Messenger 对象。
     * 通过该 Messenger 发送的任何消息都会被指定的 Handler 所接收,就像直接调用 Handler.sendMessage(Message)一样
     * 
     * @param target 传入一个用于接受消息的 Handler对象。
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }

Messenger 译为信使,用于在不同的进程间传递 Message 信息,是 Service服务端与 Activity客户端之间通信的桥梁。
在这里插入图片描述

2. 简单例子Demo

简单的例子说明:首先创建一个服务端,可以让其处于额外的进程中,其次创建一个客户端,也就是我们的Activity,点击发送信息按钮后,客户端向服务端发送信息,并且服务端在接收到信息后,返回信息回给客户端。

2.1 创建服务端

创建一个服务端,取名为 MessengerService,并在清单文件中设置属性,让其处以额外的进程中,代码如下:

public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    public static final int MSG_FROM_SERVICE = 2;
    public static final String SERVICE_REPLY_MSG_KEY = "SERVICE_REPLY_MSG";
    private Messenger mMessenger = new Messenger(new MyHandler());

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    public static class MyHandler extends Handler {

        @Override
        public void handleMessage(@NonNull Message msgFromClient) {
            super.handleMessage(msgFromClient);
            Bundle sendByClientBundle = msgFromClient.getData();
            String clientMsg = sendByClientBundle.getString(MessengerServiceTestActivity.CLIENT_SEND_MSG_KEY);
            Log.e(TAG, "client send message: " + clientMsg);
            switch (msgFromClient.what) {
                case MessengerServiceTestActivity.MSG_FROM_CLIENT:
                    try {
                        //模拟耗时4秒,服务端回应信息给客户端
                        Thread.sleep(4000);
                        Message replyClientMsg = new Message();
                        replyClientMsg.what = MSG_FROM_SERVICE;
                        Bundle bundle = new Bundle();
                        bundle.putString(SERVICE_REPLY_MSG_KEY, "My Name is Jere");
                        replyClientMsg.setData(bundle);
                        //回应消息给客户端
                        msgFromClient.replyTo.send(replyClientMsg);
                    } catch (InterruptedException | RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    break;
            }
        }
    }
}

在清单文件中设置该服务,并设置其 process 属性,让其处于额外的进程中,如newprocess。

<service
    android:name=".messenger.MessengerService"
    android:enabled="true"
    android:exported="true"
    android:process=":newprocess"/>

这样设置好后 MessengerService 就处在了 com.example.servicetest:newprocess 进程中。

2.2 创建客户端

创建一个客户端,取名为:MessengerServiceTestActivity,代码如下:

public class MessengerServiceTestActivity extends AppCompatActivity {
    private static final String TAG = "MessengerServiceTestActivity";
    public static final int MSG_FROM_CLIENT = 1;
    public static final String CLIENT_SEND_MSG_KEY = "CLIENT_SEND_MSG";
    private Messenger mMessenger;
    private boolean isBoundService;
    private Messenger mReplyToMessenger = new Messenger(new ServiceReplyToMessengerHandler());

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //利用服务端返回的 IBinder,新创建一个Messenger对象
            mMessenger = new Messenger(service);
            isBoundService = true;
            Log.d(TAG, "onServiceConnected: ");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBoundService = false;
            Log.d(TAG, "onServiceDisconnected: ");
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger_service_test);
		
		//点击按钮,客户端向服务端发送信息,并指定了用于接收服务端返回信息的 Messenger 对象
        Button sendMsgBtn = findViewById(R.id.send_message_btn);
        sendMsgBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message message = new Message();
                message.what = MSG_FROM_CLIENT;
                Bundle sendToServiceBundle = new Bundle();
                sendToServiceBundle.putString(CLIENT_SEND_MSG_KEY, "Hi! What's your name!");
                message.setData(sendToServiceBundle);

                //指定用于接收服务端返回信息的 Messenger
                message.replyTo = mReplyToMessenger;
                try {
                    //通过调用 Messenger 中的 send() 方法,将消息发送给服务端
                    mMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        //绑定服务
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //如果绑定了服务,则解绑服务
        if (isBoundService) {
            unbindService(serviceConnection);
            isBoundService = false;
        }
    }

    public static class ServiceReplyToMessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MessengerService.MSG_FROM_SERVICE:
                    Bundle serviceReplyBundle = msg.getData();
                    String name = serviceReplyBundle.getString(MessengerService.SERVICE_REPLY_MSG_KEY);
                    Log.e(TAG, "receiver service message info: " + name);
                    break;
                default:
                    break;
            }
        }
    }
}

同时看一下其在清单文件中的配置:

<activity android:name=".messenger.MessengerServiceTestActivity"/>

没有额外的为客户端设置进程属性,这是客户端位于 com.example.servicetest 进程中。

2.3 测试

点击按钮后,客户端向服务端发送 “Hi! What’s your name!”,服务端在接收到信息后,返回给客户端 “My Name is Jere”,注意看 LOG 信息,其处于的进程是不一样的。

//服务端接收到客户端发送过来的信息
com.example.servicetest:newprocess E/MessengerService: client send message: Hi! What's your name!
//客户端接收到服务端返回的信息
com.example.servicetest E/MessengerServiceTestActivity: receiver service message info: My Name is Jere

End~
本文只是简单的对 Messenger 进行初探~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值