AIDL を使って Service を内部利用したり一般公開したい時ってあると思います。
Read/Write 出来る Service だけれど、一般公開するにあたっては ReadOnly な AIDL を公開したい。
けれど、一つの Service で実現されているにも関わらず、権限や利用方法によっていくつも AIDL と Service を増やすのは、コードの肥大化、また少ないメモリで動作する Android 端末上で多くの Service を作ることでメモリ不足の原因ともなります。
Service の onBinder() 内で、何故 Binder を返しているか、不思議に思ったことはありませんか?
実はあの部分で Service のインタフェースを切り替えることが出来るのです。
まず、それぞれの AIDL を作ります。 (今回は面倒なので ReadOnly と WriteOnly だけ作ります。)
- IReadTestService.aidl
interface IReadTestService { int getNum(); }
- IWriteTestService.aidl
interface IWriteTestService { void setNum(int num); }
AIDL を作ったら、 Service の onBind() 内で振り分けをすることが出来ます。
- TestService.java
@Override public IBinder onBind(Intent intent) { if (IReadTestService.class.getName().equals(intent.getAction())) { return mReadTestServiceIf; } else if (IWriteTestService.class.getName.equals(intent.getAction())) { return mWriteTestServiceIf; } return null } private static int mNum = 0; /** 読み込み用 AIDL の実装 */ private IReadTestService.Stub mReadTestService = new IReadTestService.Stub() { @Override public int getNum() { return mNum; } }; /** 書き込み用 AIDL の実装 */ private IWriteTestService.Stub mWriteTestService = new IWriteTestService.Stub() { @Override public void setNum(int num) { mNum = num; } };
このように返却する binder を別々にすれば、一つの Service を複数の AIDL から利用することが出来るのです。
自分自身からのサービス呼び出しや信頼出来るアプリ(自分の作ったアプリなど)からは読み書き出来る AIDL を利用し、一般公開には Read Only として AIDL を公開するということも出来るようになります。
また、 intent.getAction() == null な場合は、ローカルからの (AIDL 経由でない) Service 呼び出しですので、さらにそこで振り分けることも出来ます。
追記
実際メモリ使用量が減ってるかは知らない。