• Android跨进程通信Messenger*


    一.概述

    我们可以在客户端发送一个Message给服务端,在服务端的handler中会接收到客户端的消息,然后进行对应的处理,处理完成后,再将结果等数据封装成Message,发送给客户端,客户端的handler中会接收到处理的结果。

    有这么几个特点:

    • 基于Message,相信大家都很熟悉

    • 支持回调的方式,也就是服务端处理完成长任务可以和客户端交互

    • 不需要编写aidl文件

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

    二.应用

    package com.imooc.messenger_server;
    
    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;
    
    public class MessengerService extends Service {
    
        private static final int MSG_SUM = 0x110;
    
        //最好换成HandlerThread的形式
        private Messenger mMessenger = new Messenger(new Handler() {
            @Override
            public void handleMessage(Message msgfromClient) {
                Message msgToClient = Message.obtain(msgfromClient);//返回给客户端的消息
                switch (msgfromClient.what) {
                    //msg 客户端传来的消息
                    case MSG_SUM:
                        msgToClient.what = MSG_SUM;
                        try {
                            //模拟耗时
                            Thread.sleep(2000);
                            msgToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2;
                            msgfromClient.replyTo.send(msgToClient);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
                }
                super.handleMessage(msgfromClient);
            }
        });
    
        @Override
        public IBinder onBind(Intent intent)  {
            return mMessenger.getBinder();
        }
    }

    服务端就一个Service,可以看到代码相当的简单,只需要去声明一个Messenger对象,然后onBind方法返回mMessenger.getBinder();

    然后坐等客户端将消息发送到handleMessage想法,根据message.what去判断进行什么操作,然后做对应的操作,最终将结果通过 msgfromClient.replyTo.send(msgToClient);返回。

    可以看到我们这里主要是取出客户端传来的两个数字,然后求和返回,这里我有意添加了sleep(2000)模拟耗时,注意在实际使用过程中,可以换成在独立开辟的线程中完成耗时操作,比如和HandlerThread结合使用。

    注册文件

    <service
                android:name=".MessengerService"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="com.zhy.aidl.calc"></action>
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </service>

    (二)客户端

    Activity

    package com.imooc.messenger_client;
    
    import android.content.ComponentName;
    import android.content.Context;
    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.LinearLayout;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private static final int MSG_SUM = 0x110;
    
        private Button mBtnAdd;
        private LinearLayout mLyContainer;
        //显示连接状态
        private TextView mTvState;
    
        private Messenger mService;
        private boolean isConn;
    
    
        private Messenger mMessenger = new Messenger(new Handler() {
            @Override
            public void handleMessage(Message msgFromServer)  {
                switch (msgFromServer.what)  {
                    case MSG_SUM:
                        TextView tv = (TextView) mLyContainer.findViewById(msgFromServer.arg1);
                        tv.setText(tv.getText() + "=>" + msgFromServer.arg2);
                        break;
                }
                super.handleMessage(msgFromServer);
            }
        });
    
    
        private ServiceConnection mConn = new ServiceConnection()  {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = new Messenger(service);
                isConn = true;
                mTvState.setText("connected!");
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name)  {
                mService = null;
                isConn = false;
                mTvState.setText("disconnected!");
            }
        };
    
        private int mA;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)  {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //开始绑定服务
            bindServiceInvoked();
    
            mTvState = (TextView) findViewById(R.id.id_tv_callback);
            mBtnAdd = (Button) findViewById(R.id.id_btn_add);
            mLyContainer = (LinearLayout) findViewById(R.id.id_ll_container);
    
            mBtnAdd.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v)  {
                    try  {
                        int a = mA++;
                        int b = (int) (Math.random() * 100);
    
                        //创建一个tv,添加到LinearLayout中
                        TextView tv = new TextView(MainActivity.this);
                        tv.setText(a + " + " + b + " = caculating ...");
                        tv.setId(a);
                        mLyContainer.addView(tv);
    
                        Message msgFromClient = Message.obtain(null, MSG_SUM, a, b);
                        msgFromClient.replyTo = mMessenger;
                        if (isConn)  {
                            //往服务端发送消息
                            mService.send(msgFromClient);
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
    
        }
    
        private void bindServiceInvoked()  {
            Intent intent = new Intent();
            intent.setAction("com.zhy.aidl.calc");
            bindService(intent, mConn, Context.BIND_AUTO_CREATE);
            Log.e(TAG, "bindService invoked !");
        }
    
        @Override
        protected void onDestroy()  {
            super.onDestroy();
            unbindService(mConn);
        }
    }

    代码也不复杂,首先bindService,然后在onServiceConnected中拿到回调的service(IBinder)对象,通过service对象去构造一个mService =new Messenger(service);然后就可以使用mService.send(msg)给服务端了。

  • 相关阅读:
    获得目标服务器中所有数据库名、表名、列名
    SQL Server 2008 安装SQLDMO.dll
    三层交换原理
    NAT地址转换原理全攻略
    C#中显/隐式实现接口及其访问方法
    As,is含义?using 语句
    c#泛型约束
    C#几个经常犯错误汇总
    C#--深入分析委托与事件
    markdown基础
  • 原文地址:https://www.cnblogs.com/chenxibobo/p/9651861.html
Copyright © 2020-2023  润新知