출처: http://i5on9i.blogspot.kr/2013/10/messenger.htmlhttp://rosaria1113.tistory.com/242

Messenger 개념

Handler 가 하나의 process 내에서 여러 Thread 들이 통신할 때 사용할 수 있다. 그런데 이 Handler 를 process 들끼리의 통신에 사용할 수는 없다. 이 때 사용하는 것이 Messenger 라는 녀석이다. 이 녀석을 이용해서 Handler 를 감싸면, 중간에 Marshaling 같은 부분들을 (Parcel 같은.) Messenger 가 해주고, 프로그래머 입장에서는 process 사이에서도 Handler 와 같은 interface 를 사용할 수 있게 돼서 프로그래밍이 좀 더 편하게 된다.

그러니까 정리해서 얘기하면 process 사이에서 Handler 를 사용할 수 있게 해 주는 녀석 정도로 이해하면 될 듯 하다.

아래 좀 다른 형태의 설명이 있으니 참고하세요.

Messenger 는 특정 Handler 를 감싸는 클래스입니다. 가장 큰 특징은 바로, 이 Messenger 가 Parcelable 인터페이스를 구현하고 있다는 점 입니다. Handler 자체는 다른 프로세스로 넘겨 줄 수 없지만, 이를 Messenger 로 감싸면, 해당 Handler 로 원격에서 메세지를 전할 수 있는 Messenger 인스턴스를 생성할 수 있고, 이 Messenger 인스턴스는 한 프로세스에서 다른 프로세스로 이동 할 수 있습니다. 그래서, 복잡한 AIDL 을 정의하지 않고도 간편하게 Message 에 기반한 IPC 작업을 수행할 수 있습니다. 예제 코드를 살펴 보도록 하지요.

출처 : 안드로이드 Handler 이야기 - Messenger Service - |작성자 휴우, 2011/08/18



Messenger 예제

간단한 예제는 아래에서 찾을 수 있습니다.
[Android/안드로이드] Messenger 를 이용한 IPC.( Service binding ), 2012/05/21


이 Messenger 를 이용해서 Service 와 Activity 가 통신하는 방법은 AIDL 에서 설명한 내용과 같다. 다시 정리하면 아래와 같다.

  • Service -> Activity
    Service 와 bind 되고 나서 Service 에 Activity 에서 생성된 Messenger() 를 Service에 넘겨줘서 Service 가 이것을 이용해서 Activity 에 원하는 Message 를 전달할 수 있게 해준다.
  • Activity -> Service
    Service 는 onBind() 에서 Message class type 을 넘겨준다(return). 이 Message 가 Bind 될 때 onServiceConnected 로 넘어오는 Binder 이다. 이녀석을 이용해서 Activity 는 Service 에 원하는 Message 를 전달하게 된다.
  • 코드
Messenger 는 특정 Handler 인스턴스의 리퍼런스를 갖고 있으며, 이를 이용하여 해당 Handler 로 메세지를 보낼 수 있습니다. 이를 이용하여, 프로세스간 메세지 기반 커뮤니케이션을 수행할 때 활용될 수 있습니다. 

[출처] 안드로이드 Handler 이야기 - Messenger Service - |작성자 휴우


A 프로세스 -> B 프로세스로 Handler 인스턴스를 그냥 넘길수는 없다. Parcelable 인터페이스를 구현하고 있는 Messenger로 감싸면 전송이 가능하다.  (Parcelable 인터페이스 : 객체 직렬화를 위한 인터페이스, 생성된 객체를 파일이 저장하거나 스트림을 통해 보내는 것이 가능


아래 예제는 2개의 Android Application을 생성하고 TestMessager2 어플에서 TestMessenger1에 있는 mHander로 메시지를 보내는 방법이다.

mHandler(service)에서 Client(호출하는곳)으로 응답 메시지를 보내야 하는 경우 

  1. Client 에 핸들러를 생성, Messenger로 만든다.

  2. replyTo 필드를 사용해서 1번으로 만들어진 인스턴스를 추가

  3. Server는 수신된 Message의 replyTo 필드에서 Client Messener를 꺼내서 응답 메시지를 전달


TestMessenger1

MessengerService.java

public class MessengerService extends Service {

private static final String TAG = "MessengerService";

private Handler mHandler = new Handler() {

public void handleMessage(Message msg) {

switch (msg.what) {

case 1:

Log.d(TAG, "mHandler.case 1");

break;

}

}

};

public void onCreate() {

super.onCreate();

Log.d(TAG, "MessengerService onCreate()");

}


@Override

public IBinder onBind(Intent arg0) {

Log.d(TAG, "MessengerService onBind()");

return new Messenger(mHandler).getBinder();

}

}


AndroidManifest.xml

<service 

android:name="com.example.testmessenger1.MessengerService"

android:process=":remote">

<intent-filter >

<action android:name="com.example.testmessenger1.MessengerService"/>

</intent-filter>

</service>

AndroidManifest.xml을 위와 같이 수정해주지 않으면 TestMessenger2에서 

"java.lang.SecurityException: Not allowed to bind to service Intent { cmp=com.example.testmessenger1/.MessengerService }" 이 뜬다.


TestMessenger2

MainActivity.java

public class MainActivity extends Activity {


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button btn = (Button)findViewById(R.id.btn);

btn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

ComponentName cn = new ComponentName("com.example.testmessenger1",

    "com.example.testmessenger1.MessengerService");

Intent intent = new Intent();

intent.setComponent(cn);

            

ServiceConnection conn = new ServiceConnection() {

@Override

public void onServiceDisconnected(ComponentName name) {}

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

Messenger messenger = new Messenger(service);

Message msg = Message.obtain(null, 1);

try {

messenger.send(msg);

} catch (RemoteException e) {

}

}

};

bindService(intent, conn, Context.BIND_AUTO_CREATE);

}

});

}

}

Context.BIND_AUTO_CREATE flag를 사용해서인지 TestMessenger1이 실행되지 않아도 호출 된다.




주의: AIDL 은 오직 Client 의 요청의 결과가 즉시 return 되어야 하기 때문에, Service 단에서 동시에 여러 스레드를 통해 개별 요청을 처리해야 하는 경우에만 필요합니다. 만일 그렇지 않은 경우에는 Messenger 클래스를 활용하세요.

[출처] 안드로이드 Handler 이야기 - Messenger Service - |작성자 휴우


Messenger 이외의 방법

Service 와 Activity 간 통신을 하는 좋은 방법
Android Example: Communication between Activity and Service using Messaging - Philipp's Tech Blog


Broadcast 를 이용해 Service 에서 Activity 로 data 전달
Android Coding: Pass data from Service to Activity


AIDL
위의 방법 외에 Service 에서 Activity 로 원하는 정보를 전달하는 방법은 aidl 을 사용할 수 있다. aidl 사용법 을 참고하자.



Messenger 로 Object 전달

Message.obj

[see also. 1] 에 보면, seperate processes 에서는 Messenger 의 obj 전달이 불가능하다고 하는 듯 하다. 하지만 하나의 process 에 Service 와 Acitivity 가 같이 있는 경우라면 Message.obj 에 원하는 object 를 넣고 전달하는 것이 가능하다.

Bundle

[See Also. 1] 에 따르면, seperate process 라면 Message.obj 를 사용해서 원하는 object 를 넘기는 것은 불가능하고, 대신에 Bundle 을 사용해야 한다고 한다.

Handler 에서 Bundle 은 마치 hashMap 처럼 사용할 수 있다. key 와 value 를 이용해서 값을 유연하게 넣을 수 있다. 그리고 이 녀석을 Message 에 실어서 Handler 로 보내면 된다.

Bundle 관련 예제 : http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/


'Programing > Android' 카테고리의 다른 글

개발 협업을 위한 안드로이드 디자인 가이드 #01  (0) 2016.05.08
Resolution and DP (Density Independent Pixels)  (0) 2016.05.07
BroadcastReceiver  (0) 2016.05.06
ANR (Application Not Responding)  (0) 2016.05.06
Process and Thread  (0) 2016.05.04

+ Recent posts