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


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

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


先写上基本代码:

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 中部分代码

<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接口。

    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源码是如何发消息的

    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对象进行发送消息。


IMessenger.aidl
内容如下

package android.os;

import android.os.Message;

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

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




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。