기타치는 개발자

[Android]Messenger를 사용하여 앱 간 통신하기 본문

안드로이드/Android

[Android]Messenger를 사용하여 앱 간 통신하기

던킨팬더 2016. 10. 17. 16:13

이번에는 Service 사용해서 앱과 앱 사이 통신하는 부분을 정리해보려 합니다. 


 기본적으로 앱간 통신을 하게 될때 BroadcastReceiver, Intent 등을 많이 쓰게됩니다. 

어려운 작업 없이 Receiver Action 정의를 해주거나 Intent scheme 정의합니다. 하지만 BroadcastReceiver 같은경우 시스템쪽으로 sendBroadCast 를 해주고 받아오는것이라 찝찝한 부분이 있습니다. 또한 구글 정책상 버전이 올라갈수록 manifest.xml Receiver 에  명시적으로 Action명을 선언하는것을 줄여간다고 하였습니다. 


저 같은경우 아래와 같은 요건사항이 있을경우 Messenger 방식의 Service 를 사용하여 작업하였습니다.

  • 앱간 요청에 대한 응답 필요
  • 서로 앱 동작 및 상태 체크 필요
  • onBinder 를 사용하나 .aidl 파일을 미생성


Messenger사용하여 바인딩하기


.aidl 파일을 작성하여 하는 방식이 있으나 사용방법도 어렵고 구글에서도 아래와같이 안내하고 있습니다.



 Messenger 객체를 이용하여 하는것을 권하고 있으며 Messenger 객체는 객체 생성시 Handler 를 파라미터로 받으며 서로 통신시에 Message 를 사용하여 사용하게됩니다.  내부적으로 IMessger.aidl 파일을 관리한다고 들었습니다. 정확하진않으나 Messenger 로 Message 를 Send할경우 해당 MEssenger 에서 받은 후 지정된 Handler 로 전달 해주는것 같습니다. 실제로는 Handler 부분에 msg.what 부분만 잘 정의 하여 사용하면 될것같습니다. 아래 코드를 보시면 이해하기 쉬울 것 같습니다. 




서비스 구현 소스 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class AppToAppService extends Service {
    Messenger mMessenger = null;
 
    public AppToAppService() {
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
        mMessenger = new Messenger(new AppToApphandler(getApplicationContext()));
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
 
cs



호출하는 앱에서 bindService()를 호출하였을때 호출되는 부분에 onBind 매소드에 Messenger 를 반환하는것을 볼수있습니다. 

Messenger 은 따로 정의돈 Handler 를 파라미터로합니다 처리된 Handler 는 아래와같습니다.


Messenger 처리 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class AppToApphandler extends Handler implements AppToAppConstant {
 
    Context mContext;
    Messenger messenger = null;
 
    AppToApphandler(Context context) {
        this.mContext = context;
    }
 
    @Override
    public void handleMessage(Message msg) {
 
        if (messenger == null && msg.replyTo != null) {
            messenger = msg.replyTo;
            AppToAppManager.with(mContext).setMessenger(messenger);
        }
        Bundle bundle = msg.getData();
        switch (msg.what) {
            case ACLIENT_REQUEST_ADD:
                AppToAppManager.with(mContext).send(ACLIENT_RESPONSE_ADD);
                break;
            case ACLIENT_SEND_TIMESTAMP:
                if (bundle != null) {
                    long timeStamp = bundle.getLong("timestamp");
                    Toast.makeText(mContext, "BClient Response " + timeStamp, Toast.LENGTH_SHORT).show();
                }
                break;
 
            case ACLIENT_REQUEST_FORCEEXIT:
                String exceptionString = null;
                exceptionString.charAt(0);
                break;
            case DISCONNETCLIENTA:
                AppToAppManager.with(mContext).setMessenger(null);
                break;
 
            default:
                super.handleMessage(msg);
        }
    }
}
 
cs

기존 Handler 사용과 동일하며 data 전달은 Bundle로 사용합니다 

- Custom Object를 전달할경우 동일 Class파일이 있어야하며 Parcelable 을 implements 를 해준 객체 이여야 합니다 .

  또한 bundle 에서 사용할시에는 bundle.setClassLoader()를 사용하여 해당 Object에 대한 class정보를 지정해주어야 합니다. 


위와 같은경우 요청에 의한 응답을 위해 메세지 전송시에 호출 쪽의 Messenger 을replyTo 사용하여 전달하게 됩니다. 전달된 Messenger 는 동일하게 Handler 를 포함하고 있으며 처리 방식은 동일 합니다. 


아래 샘플은 2개의 모듈로 구성되어있으며 A 모듈에서 B모듈로 bindService를 호출하게됩니다.


 https://github.com/dunkindonass/AppToAppSample.git