AIDL 사용법
여기서는 대략적인 사용법만 이야기 하겠다. 자세한 사항은 sdk 에 있는 예제 코드를 확인하도록 하자.그리고 이 예제는 내가 test 한 예제이다.
Example Files Paths
- <sdk_path>\samples\android-17\ApiDemos\src\com\example\android\apis\app\IRemoteService.aidl
- <sdk_path>\samples\android-17\ApiDemos\src\com\example\android\apis\app\IRemoteServiceCallback.aidl
- <sdk_path>\samples\android-17\ApiDemos\src\com\example\android\apis\app\ISecondary.aidl
- <sdk_path>\samples\android-17\ApiDemos\src\com\example\android\apis\app\RemoteService.java
동작
동작은 Messenger 로 통신하는 것과 다를 바 없다. 그래서 "Messenger 개념 및 사용법"를 참고하는 것도 도움이 될 것이다.여기서 activity 와 service 사이의 통신을 가능하도록 하기 위해서 아래와 같은 작업이 필요하다.
- activity 에게 service 의 reference 를 줘야하고,
- service 에게는 activity 의 handler 를 넘겨 줘야한다.
이것은 코드에서 다음과 같이 처리되었다.
- activity.handler 는 onServiceConnected 에서 service 로 전달되고,(mService.registerCallback())
- service의 reference 는 bindService 를 통해서 처리할 수 있다.
이제 좀 더 구체적으로 살펴보자.
aidl 로 IRemoteService 라는 interface 를 정의했다고 가정하자.
inteface 를 aidl 에 정의해 놓고 compile 을 하면
- inteface -> abstract interface
- static abstract class Stub extends Binder implements IRemoteService
가 생긴다.(아래 코드 참조)
그 이후는 일반적으로 service 를 bind 하고 사용하는 모습과 같다.
bindService 부터 mCallback 이 호출되는 모습을 대략적으로 그려봤다. 대략 요약하면
- Service 에 interface 로 register 를 만들고,
- 서비스가 connected 되면(onServiceConectted), register 를 통해서 Activity 에 있는 함수(callback) 를 Service 에 등록 해 놓는다.
- 그리고 나중에 Service 에서 필요할 때 호출한다.
- 그리고 Activity 에서 호출되는 함수(callback) 는 handler 를 이용해서 msg 를 처리한다.(그렇지 않으면, 동기화에 문제가 있을 수 있다.)
아래 그림은 "새창에서 열기" 로 열어야 크게 볼 수 있다.
IRemoteService.aidl >> IRemoteService.class
package com.example.samples.mp3playerremote; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; public abstract interface IRemoteService extends IInterface { public abstract void registerCallback(IRemoteServiceCallback paramIRemoteServiceCallback) throws RemoteException; public abstract void unregisterCallback(IRemoteServiceCallback paramIRemoteServiceCallback) throws RemoteException; public static abstract class Stub extends Binder implements IRemoteService { private static final String DESCRIPTOR = "com.example.samples.mp3playerremote.IRemoteService"; static final int TRANSACTION_registerCallback = 1; static final int TRANSACTION_unregisterCallback = 2; public Stub() { attachInterface(this, "com.example.samples.mp3playerremote.IRemoteService"); } public static IRemoteService asInterface(IBinder obj) { if (obj == null) { return null; } IInterface iin = obj.queryLocalInterface("com.example.samples.mp3playerremote.IRemoteService"); if ((iin != null) && ((iin instanceof IRemoteService))) { return (IRemoteService)iin; } return new Proxy(obj); } public IBinder asBinder() { return this; } public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case 1598968902: reply.writeString("com.example.samples.mp3playerremote.IRemoteService"); return true; case 1: data.enforceInterface("com.example.samples.mp3playerremote.IRemoteService"); IRemoteServiceCallback _arg0 = IRemoteServiceCallback.Stub.asInterface(data.readStrongBinder()); registerCallback(_arg0); reply.writeNoException(); return true; case 2: data.enforceInterface("com.example.samples.mp3playerremote.IRemoteService"); IRemoteServiceCallback _arg0 = IRemoteServiceCallback.Stub.asInterface(data.readStrongBinder()); unregisterCallback(_arg0); reply.writeNoException(); return true; } return super.onTransact(code, data, reply, flags); } private static class Proxy implements IRemoteService { private IBinder mRemote; Proxy(IBinder remote) { this.mRemote = remote; } public IBinder asBinder() { return this.mRemote; } public String getInterfaceDescriptor() { return "com.example.samples.mp3playerremote.IRemoteService"; } public void registerCallback(IRemoteServiceCallback cb) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken("com.example.samples.mp3playerremote.IRemoteService"); _data.writeStrongBinder(cb != null ? cb.asBinder() : null); this.mRemote.transact(1, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } public void unregisterCallback(IRemoteServiceCallback cb) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken("com.example.samples.mp3playerremote.IRemoteService"); _data.writeStrongBinder(cb != null ? cb.asBinder() : null); this.mRemote.transact(2, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } } }
AIDL in intelliJ
http://stackoverflow.com/questions/15673319/android-intellij-idea-12-aidlandroid-idl-compiler 가 따로 compile 을 해준다. 하지만 syntax 에 대한 검사를 미리 해주지 않기 때문에, syntax 를 잘 체크해야 한다.
댓글 없음:
댓글 쓰기