• Android消息处理(二)进程间通信


    使用Handler+Message的方式进行通信,都是在同一个进程中,从线程持有一个主线程的Handler对象,并向主线程发送消息。

    而Android既然可以使用bindler机制进行跨进行通信,所以我们当然可以将Handler与bindler结合起来进行跨进程发送消息。

    Messenger:信使

    官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。

    一般使用方法如下:

    1. 远程通过
      mMessenger = new Messenger(mHandler) 
      创建一个信使对象
    2. 客户端使用bindlerService请求连接远程
    3. 远程onBind方法返回一个bindler
      return mMessenger.getBinder();
    4. 客户端使用远程返回的bindler得到一个信使(即得到远程信使)
      public void onServiceConnected(ComponentName name, IBinder service)
      {
           rMessenger = new Messenger(service);
        ......
      }
      这里虽然是new了一个Messenger,但我们查看它的实现
      /**
           * Create a Messenger from a raw IBinder, which had previously been
           * retrieved with {@link #getBinder}.
           *
           * @param target The IBinder this Messenger should communicate with.
           */
          public Messenger(IBinder target) {
              mTarget = IMessenger.Stub.asInterface(target);
          }
      发现它的mTarget是通过Aidl得到的,实际上就是远程创建的那个。
    5. 客户端可以使用这个远程信使对象向远程发送消息:rMessenger.send(msg);这样远程服务端的Handler对象就能收到消息了,然后可以在其handlerMessage(Message msg)方法中进行处理。(该Handler对象就是第一步服务端创建Messenger时使用的参数mHandler).

    经过这5个步骤貌似只有客户端向服务端发送消息,这样的消息传递是单向的,那么如何实现双向传递呢?

    首先需要在第5步稍加修改,在send(msg)前通过msm.replyTo = mMessenger将自己的信使设置到消息中,这样服务端接收到消息时同时也得到了客户端的信使对象了,然后服务端可以通过

    //得到客户端的信使对象,并向它发送消息
    cMessenger = msg.replyTo;
    cMessenger.send(message);

    即完成了从服务端向客户端发送消息的功能,这样客服端可以在自己的Handler对象的handlerMessage方法中接收服务端发送来的message进行处理。双向通信宣告完成。

    下面改写ApiDemos工程实现Messenger通信

    MessengerService.java

    package com.xwangly.apidemo.app;
    
    import java.util.Random;
    
    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;
    
    public class MessengerService extends Service {
    	private String TAG = "MessengerService";
    
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		Log.i(TAG, "onDestroy");
    		cMessenger = null;
    		super.onDestroy();
    	}
    
    	@Override
    	public boolean onUnbind(Intent intent) {
    		// TODO Auto-generated method stub
    		Log.i(TAG, "onUnbind");
    		return super.onUnbind(intent);
    	}
    
    	static final int MSG_REGISTER_CLIENT = 1;
    	static final int MSG_UNREGISTER_CLIENT = 2;
    	static final int MSG_SET_VALUE = 3;
    
    	private Random random = new Random();
    
    	private Handler mHandler = new Handler() {
    
    		@Override
    		public void handleMessage(Message msg) {
    			// TODO Auto-generated method stub
    			Log.i(TAG, "handleMessage");
    			switch (msg.what) {
    			case MSG_SET_VALUE:
    				try {
    					Message message = Message.obtain(null,
    							MessengerService.MSG_SET_VALUE);
    					message.arg1 = random.nextInt(100);
    					
    					//得到客户端的信使对象,并向它发送消息
    					cMessenger = msg.replyTo;
    					cMessenger.send(message);
    				} catch (RemoteException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				break;
    			default:
    				super.handleMessage(msg);
    			}
    
    		}
    	};
    
    	/**
    	 * 自己的信使对象
    	 */
    	private Messenger mMessenger = new Messenger(mHandler);
    
    	/**
    	 * 客户的信使
    	 */
    	private Messenger cMessenger;
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		Log.i(TAG, "onBind");
    		//返回自己信使的bindler,以供客户端通过这个bindler得到服务端的信使对象(通过new Messenger(bindler))
    		return mMessenger.getBinder();
    	}
    
    	@Override
    	public void onRebind(Intent intent) {
    		// TODO Auto-generated method stub
    		Log.i(TAG, "onRebind");
    
    	}
    
    }

    MessengerServiceActivities.java

    package com.xwangly.apidemo.app;
    
    import com.xwangly.apidemo.R;
    
    import android.app.Activity;
    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.util.Log;
    import android.view.View;
    import android.widget.TextView;
    
    public class MessengerServiceActivities {
    	public static class Binding extends Activity implements
    			View.OnClickListener {
    		private String TAG = "Binding";
    
    		TextView mCallbackText;
    
    		private boolean isBound;
    
    		@Override
    		protected void onCreate(Bundle savedInstanceState) {
    			// TODO Auto-generated method stub
    			super.onCreate(savedInstanceState);
    			setContentView(R.layout.messenger_service_binding);
    			findViewById(R.id.bind).setOnClickListener(this);
    			findViewById(R.id.unbind).setOnClickListener(this);
    
    			mCallbackText = (TextView) findViewById(R.id.callback);
    			mCallbackText.setText("Not attached.");
    
    		}
    
    		private Handler mHandler = new Handler() {
    			@Override
    			public void handleMessage(Message msg) {
    				Log.i(TAG, "handleMessage");
    				switch (msg.what) {
    				case MessengerService.MSG_SET_VALUE:
    					mCallbackText.setText("Received from service: " + msg.arg1);
    					break;
    				default:
    					super.handleMessage(msg);
    				}
    			}
    		};
    
    		/**
    		 * 自己的信使
    		 */
    		private Messenger mMessenger;
    		
    		/**
    		 * 远程服务的信使
    		 */
    		private Messenger rMessenger;
    		
    		private ServiceConnection connection = new ServiceConnection() {
    
    			public void onServiceConnected(ComponentName name, IBinder service) {
    				// TODO Auto-generated method stub
    				Log.i(TAG, "onServiceConnected");
    				rMessenger = new Messenger(service);
    				mMessenger = new Messenger(mHandler);
    				
    				sendMessage();
    			}
    
    
    			public void onServiceDisconnected(ComponentName name) {
    				// TODO Auto-generated method stub
    				rMessenger = null;
    			}
    		};
    
    		public void onClick(View v) {
    			// TODO Auto-generated method stub
    			Intent intent = new Intent(
    					"com.xwangly.apidemo.app.messenger_service");
    			switch (v.getId()) {
    			case R.id.bind:
    				if (!isBound) {
    					isBound = bindService(intent, connection, BIND_AUTO_CREATE);
    					//isBound = true;
    				}else {
    					sendMessage();
    				}
    				break;
    			case R.id.unbind:
    				if (isBound) {
    					unbindService(connection);
    					isBound = false;
    				}
    				break;
    			default:
    				break;
    			}
    		}
    		
    		/**
    		 * 使用服务端的信使向它发送一个消息。
    		 */
    		private void sendMessage() {
    			// TODO Auto-generated method stub
    			Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE);
    			message.replyTo = mMessenger;
    			try {
    				rMessenger.send(message);
    			} catch (RemoteException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    }

    AndroidManifest.xml相关配置如下:

    		<service android:name=".app.MessengerService" >
    			<intent-filter>
    				<action android:name="com.xwangly.apidemo.app.messenger_service" />
    			</intent-filter>
    		</service>
            <activity android:name=".app.MessengerServiceActivities$Binding"
                    android:label="@string/activity_messenger_service_binding"
                    android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
  • 相关阅读:
    luogu_P1850 换教室
    luogu_P3224 [HNOI2012]永无乡
    luogu_P1064 金明的预算方案
    luogu_P2014 选课
    luogu_P3372 【模板】线段树 1(动态开点)
    luogu_P2852 [USACO06DEC]牛奶模式Milk Patterns
    luogu_P1941 飞扬的小鸟
    luogu_P2678 跳石头
    luogu_P1638 逛画展
    【Tyvj2046】掷骰子
  • 原文地址:https://www.cnblogs.com/blueofsky/p/2303314.html
Copyright © 2020-2023  润新知