連載
» 2012年06月15日 00時00分 UPDATE

Androidで動く携帯Javaアプリ作成入門(32):Androidのプロセス間通信を自由自在にするAIDL (1/3)

[緒方聡,株式会社イーフロー]

 前回の「Android 4.0のサービス/プロセス間通信の基本」ではAIDLを使用した「サービス」の基本を解説しました。サービスのライフサイクル、AIDLParcelParcelableに関しては、前回の記事を参照してください。

 今回の記事で解説するサンプルアプリは、前回と同じものを使用します。以下よりダウンロードしておいてください。

なぜ「プロセス間通信」なのか?

 Androidの「サービス」は、バックグラウンドで処理を行いたい場合やバックグラウンドに常駐させたい場合に使用するケースがほとんどです。そのバックグラウンドの処理がアプリ固有であれば、同一プロセスで行い、プロセス間通信を行う必要はありません。

 つまり、「複数のアプリから使用される可能性のある処理を独立したプロセスとして切り離し、それぞれのアプリから使用できるようにサービス化しておくこと、そのサービスを利用すること」がプロセス間通信の目的です。

 例外はありますが、「Context#getSystemService(String)」で取得可能なマネージャクラスは、システムサービスのラッパー(アプリ自体でAIDLを取り込みサービスにバインドする手間を省ける)であることがほとんどです。システムサービスはそれぞれが明確な役割を持ち、システムに常駐しており、複数のアプリからの処理を受け着けるという点で、効果的なプロセス間通信であるといえます。

 開発者にとって身近なAIDLを使用するサービスの1つとして「アプリ内課金」があります。この場合、アプリからGoogle Playアプリに対して課金状況の問い合わせや課金処理の依頼を行うのですが、これをAIDLを経由してサービスのメソッド呼び出しをすると、簡潔に行えます。アプリ内課金についての詳細は、以下の記事を参照してください。

 「暗号化サービスや圧縮・展開サービスが、それぞれ同一のインターフェイスで定義されていて、アルゴリズムは異なる」ようなケースにおいて、AIDLを用いたプロセス間通信は非常に効果的です。ただし、こうした共有ライブラリ的なサービスは、ほかの開発者も巻き込む形になるため、現実的にはなかなか難しいとは思います。

 なお、ほかのプロセスに指示を送る方法としてIntent、ソケット通信、パイプ、共有メモリなどがあります。この中ではIntentが最も簡単です。Intentでの双方向のプロセス間通信は、「Androidアプリでマルチメディアを扱うための基礎知識」と、そのサンプルアプリを参照してください(正確には同一プロセス間での通信です)。

AIDLによるプロセス間通信の仕組み

 AIDLを用いたプロセス間通信は、以下のような仕組みです。

図1 AIDLによるプロセス間通信の概念図 図1 AIDLによるプロセス間通信の概念図

 上記概念図には見慣れないキーワードがいくつも出てきています。

  • Proxy
    .aidlから自動生成されるクラス。プロセス間通信におけるIPC(Inter Process Communication)の呼び出しメソッド
  • Stub
    .aidlから自動生成される抽象クラスで、サービス提供者が実装する必要がある。今回のケースでは足し算を実装したクラスを保持
  • IBinder
    IPCにおける通信を行うJava層のインターフェイス。いくつかの実装を持つ
  • libbinder
    Javaから呼び出されるネイティブライブラリ。binderとの橋渡しを行う
  • binder
    プロセス間通信を実現するカーネルモジュール。ここで、カーネルを利用してプロセス間通信が行われる

 プロセス間通信である以上、「メソッド呼び出し」というメッセージが、プロセスをまたがなければならないのですが、Androidの「binder」という仕組みは、その辺りが非常にうまく隠ぺいされています。

 目ざとい人は気が付いていると思いますが、自動生成されたStubとProxyは、「gen」フォルダに保存されています。内容は少し複雑ですが、コード量はそれほど多くはないので、AIDLのIPCを詳しく知りたい場合は、目を通してみることをお勧めします。

 AIDLはコールバックもサポートしており、その場合でもほぼ同じシーケンスでServiceからActivity側に実装されているコールバックが呼び出される形です。異なるのは、ServiceのStubは「onBind(Intent)」で返すのに対し、コールバックはActivityからServiceに、Stubをメソッドの引数で渡すところです。

 Proxyには、プロセス間通信が必要かどうかを判定する処理が実装されており、同一プロセスのメソッド呼び出しである場合、直接Stubのメソッドを呼び出し、不要な処理を省略するようになっています。ただし、常に同一プロセスのサービスを呼び出すことが分かっているのであれば、ローカルサービスとして使用し、AIDLを用意する必要はありません。

AIDLを用いたサービスの実装例

 今回は「Activity側で入力した内容をServiceに渡し、Service側で計算してActivityに返す」というサンプルを用いてAIDLを用いたサービスを説明していきます。

図2 画面イメージ 図2 画面イメージ

 左の入力フォームが左辺です。右の入力フォームが右辺です。真ん中は演算子です。演算子は四則演算のほかに、「rotate」「sum」があり、rotateの場合は右辺の値だけ左辺の配列を巡回させます。sumの場合は左辺の値をすべて合計します。

 四則演算では、左辺に配列が入力されていた場合、最初の要素以外は無視します。四則演算の和算以外は、Parcelableを引数に取るようにしています。sumの場合のみ、結果をコールバックで受け取るようにしています。

 アプリの仕様として冗長な部分がありますが、AIDLのすべての機能を使用するようにした結果です。

 次ページでは、サンプルにおけるAIDLファイルの例を紹介します。

       1|2|3 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。