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版本的 新版的源碼沒去研究,這部分應該是一致的。下面是個簡單的草圖,算是個總結。




發佈了64 篇原創文章 · 獲贊 5 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章