Android使用Messenger进行Service IPC通信分析 .

如果想要进行IPC通信,一般写一个AIDL接口,再写一个Service子类,然后实现AIDL接口 当做IBinder返回给Activity界面层。

如果不想写AIDL接口文件,只是单I线程中与Service进行通信 我们可以用Android写好的Messenger类来处理,一样能将消息传递给Service进行通信。


先写上基本代码:

  1. public class MyService extends Service {  
  2.   
  3.     Messenger messenger = null;  
  4.       
  5.       
  6.     public MyService() {  
  7.     }  
  8.   
  9.     @Override  
  10.     public void onCreate() {  
  11.         super.onCreate();  
  12.         messenger = new Messenger(handler);//实例化一个对象,并将Handler传入绑定,UI MQ消息检测   
  13.     }  
  14.       
  15.     Handler handler = new Handler(){  
  16.         public void handleMessage(android.os.Message msg) {  
  17.             Log.d("","Msg:" + msg.what + ";" + msg.obj);  
  18.         }  
  19.     };  
  20.     /* (non-Javadoc) 
  21.      * @see android.app.Service#onBind(android.content.Intent) 
  22.      */  
  23.     @Override  
  24.     public IBinder onBind(Intent arg0) {  
  25.         return messenger.getBinder();//返回Binder接口   
  26.     }  
  27.   
  28. }  
public class MyService extends Service {

	Messenger messenger = null;
	
	
	public MyService() {
	}

	@Override
	public void onCreate() {
		super.onCreate();
		messenger = new Messenger(handler);//实例化一个对象,并将Handler传入绑定,UI MQ消息检测
	}
	
	Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			Log.d("","Msg:" + msg.what + ";" + msg.obj);
		}
	};
	/* (non-Javadoc)
	 * @see android.app.Service#onBind(android.content.Intent)
	 */
	@Override
	public IBinder onBind(Intent arg0) {
		return messenger.getBinder();//返回Binder接口
	}

}

MyActivity 中部分代码

  1. <span style="white-space:pre">    </span>Messenger messenger;  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         bindService(new Intent(this,MyService.class), conn, Context.BIND_AUTO_CREATE);//一样绑定一个Connection   
  8.     }  
  9.   
  10.     private ServiceConnection conn = new ServiceConnection() {  
  11.   
  12.         @Override  
  13.         public void onServiceDisconnected(ComponentName cn) {  
  14.         }  
  15.   
  16.         @Override  
  17.         public void onServiceConnected(ComponentName cn, IBinder ibiner) {  
  18.             messenger = new Messenger(ibiner);//得到Service中的Messenger   
  19.             Log.d("","OK messenger connected........");  
  20.         }  
  21.     };  
  22.       
  23.     public void sendMsg(int what, String msg){ //这个方法就是自己的业务信息发送消息 传递到Service中 有 Handler处理。   
  24.         if (messenger == null) {  
  25.             return;  
  26.         }  
  27.         Message msg1 = Message.obtain();  
  28.         msg1.what = what;  
  29.         msg1.obj = msg;  
  30.         try {  
  31.             messenger.send(msg1);  
  32.         } catch (RemoteException e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.     }  
<span style="white-space:pre">	</span>Messenger messenger;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		bindService(new Intent(this,MyService.class), conn, Context.BIND_AUTO_CREATE);//一样绑定一个Connection
	}

	private ServiceConnection conn = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName cn) {
		}

		@Override
		public void onServiceConnected(ComponentName cn, IBinder ibiner) {
			messenger = new Messenger(ibiner);//得到Service中的Messenger
			Log.d("","OK messenger connected........");
		}
	};
	
	public void sendMsg(int what, String msg){ //这个方法就是自己的业务信息发送消息 传递到Service中 有 Handler处理。
		if (messenger == null) {
			return;
		}
		Message msg1 = Message.obtain();
		msg1.what = what;
		msg1.obj = msg;
		try {
			messenger.send(msg1);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

以上的代码非常简单。

下面看看Messenger源码其实是个包装类,它本身就是可以被IPC投递的对象,因为用了Parcelable接口。

  1. public Messenger(Handler target) { //之前传递的Handler到这里,   
  2.     mTarget = target.getIMessenger(); //得到的其实是Handler里面的IMessenger接口   
  3. }  
  4. public void send(Message message) throws RemoteException {  
  5.     mTarget.send(message);//具体有IMessenger接口发送   
  6. }  
  7.   
  8. public IBinder getBinder() {  
  9.     return mTarget.asBinder();  
  10. }  
  11. //注释我都去掉了  
    public Messenger(Handler target) { //之前传递的Handler到这里,
        mTarget = target.getIMessenger(); //得到的其实是Handler里面的IMessenger接口
    }
    public void send(Message message) throws RemoteException {
        mTarget.send(message);//具体有IMessenger接口发送
    }
    
    public IBinder getBinder() {
        return mTarget.asBinder();
    }
    //注释我都去掉了

再看看Handler源码是如何发消息的

  1. final IMessenger getIMessenger() {  
  2.     synchronized (mQueue) {  
  3.         if (mMessenger != null) {  
  4.             return mMessenger;  
  5.         }  
  6.         mMessenger = new MessengerImpl();//这个实现了IMessenger远程IPC接口,AIDL   
  7.         return mMessenger;  
  8.     }  
  9. }  
  10.   
  11. private final class MessengerImpl extends IMessenger.Stub { //实现在这个地方   
  12.     public void send(Message msg) {  
  13.         Handler.this.sendMessage(msg);//本质上还是有 Handler来发送消息   
  14.     }  
  15. }  
    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();//这个实现了IMessenger远程IPC接口,AIDL
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub { //实现在这个地方
        public void send(Message msg) {
            Handler.this.sendMessage(msg);//本质上还是有 Handler来发送消息
        }
    }

可以看出IMessenger这个远程通信IPC接口 包含了send(Message msg)方法,其本质还是获取了我们MyService中的Handler对象进行发送消息。


  1. IMessenger.aidl  
IMessenger.aidl
内容如下

  1. package android.os;  
  2.   
  3. import android.os.Message;  
  4.   
  5. /** @hide */  
  6. oneway interface IMessenger {  
  7.     void send(in Message msg);  
  8. }  
package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

以上源码是4.1版本的 新版的源码没去研究,这部分应该是一致的。下面是个简单的草图,算是个总结。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值