본문 바로가기

Android

Parcelable을 이용한 Remote Service Binding

반응형
Android에 어떤 service를 넣어두고 여기저기 각각의 Application에서 하나의 service를 필요할 때 끌어다 쓰는 것을 하고 싶었다.

... 대부분 나와있는 예제는 APK 안에 activity + service를 같이 포함해 놓고 동작시키는 예제들이 많았다.

꼭 뭔가 하고 싶은 것들은 없더라... 에효

그래서 여기 저기 뒤지다가 

하나 만들어 보았음

1. aidl 파일을 하나 만들어야 한다. IRemoteService.aidl 파일을 하나 만들어 넣는다.
package test.remoteService

interface IRemoteService{
void test1();
}

2. ADT가 포함된 eclipse 에서는 java 파일을 build하기 전에 aidl 파일이 있으면 먼저 build하여
gen 폴더에 R.java와 같이 해당 파일을 만들어 넣는다. 여기서는 IRemoteService.java 가 생성된다.

3. Remote Service를 제공하는 Service를 하나 만든다.


public class MyRemoteService extends Service{
final String TAG = "MyRemoteService";
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
if(IRemoteService.class.getName().equals(intent.getAction())){
Log.i(TAG, "return " + mBinder);
return mBinder;
}
Log.i(TAG, "return null");
return null;
}
private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public void test1() {
Log.i(TAG, "test1");
}
};
  
}

위와 같이 만들면 IRemoteService Interface를 통해 자신을 binder에 넘겨주는 Service를 생성한다.

4. AndroidManifest.XML을 수정해야 한다.

application type이 service임을 명시하고 intent-filter에 IRemoteService interface를 이용함을 명시한다.

<service android:enabled="true" android:name=".MyRemoteService">
<intent-filter>
<action android:name="test.remoteService.IRemoteService"></action>
</intent-filter>
</service>service>

5. service를 설치한다.

6. Service를 호출 할 Activity를 생성한다.

package com.skt.skaf.MyRemoteServiceCaller;

import com.test..remoteService.IRemoteService;

public class MyRemoteServiceCaller extends Activity {
    
final String TAG = "MyRemoteServiceCaller";
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Intent intent = new Intent();
intent.setComponent(service);
intent.setAction("com.skt.skaf.MyRemoteService.IRemoteService");
bindService(intent, mConnection, BIND_AUTO_CREATE);
    }
    public static final ComponentName service = new ComponentName(
            "com.skt.skaf.MyRemoteService",
            "com.skt.skaf.MyRemoteService.MyRemoteService");
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    
     if(event.getAction() == event.ACTION_DOWN){
     try {    
     Log.i(TAG, "((IRemoteService) mConnection).test1()");
((IRemoteService) mIRemoteService).test1();
} catch (RemoteException e) {
e.printStackTrace();
}
     }
    
     return super.onTouchEvent(event);
    }
    
IRemoteService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection(){
public void onServiceConnected(ComponentName className, IBinder service){
mIRemoteService = IRemoteService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName className){
mIRemoteService = null;
}
};    
}

Activity 안에는 IRemoteService를 초기화 하는 code와 Binder에 connection이 포함되어있다. 

7. build시 에러가 난다 왜냐하면 IRemoteService.java가 없다. 왜? service만들 때 생성한 코드이기 때문에 Activity 생성시에 존재하지 않기 때문이다.
다시 service 를 만든 폴더로 가서 {service}/bin/ 아래가서 해당 코드 들을 복사해서 {activity}/bin 에 복사해 넣으면 build가 성공한다.

아주 간단하게 return type이 없는 함수를 하나 호출 하여봤다.

remote Service에 object를 넘기는 것은 쉽지 안다 ㅋ
parcelable로 만들어진 objcet를 넘길 수 있다.
하지만 안드로이드에서 생성된 Context, View 등등은.. parcelable을 상속 받지 않았기 때문에 ... 힘들어 보인다는 것이다.

우찌해야할까?