AndroidはAIDLインタフェースを通じてプロセス間通信を実現


Androidの開発では、アプリケーションごとに独自のプロセスを持つことができます.UIアプリケーションを書くときに、サービスをよく使います.異なるプロセスで、オブジェクトをどのように伝達しますか?Javaではプロセス間メモリ共有は許可されていないことは明らかです.したがって、伝達対象は、オブジェクトをオペレーティングシステムが理解できる単純な形式に分割するのみで、国境を越えたオブジェクトへのアクセスの目的を達成することができる.J 2 EEでは、RMI方式を採用することで、伝達対象をシーケンス化することができる.AndroidではAIDL方式を採用する.理論上AIDLはBundleを伝えることができるが、実際には面倒だ.
AIDL(AndRoidインタフェース記述言語)は、言い訳記述言語である.コンパイラはaidlファイルを介してコードを生成する、予め定義されたインタフェースを介して2つのプロセス内部の通信プロセスの目的を達成することができる.一方のActivityにおいて、他方のサービスのいずれかのオブジェクトにアクセスする必要がある場合は、まず、オブジェクトをAIDL識別可能なパラメータ(複数のパラメータである可能性がある)に変換する、その後、AIDLを使用してこれらのパラメータを伝達し、メッセージの受信側で、これらのパラメータを使用して自分の必要なオブジェクトに組み立てる必要がある.
AIDLのIPCのメカニズムはCOMやCORBAと類似しており,インタフェースベースであるが軽量級である.プロキシクラスを使用して、クライアントと実装レイヤ間で値を渡す.AIDLを使用する場合は、2つの作業を完了する必要があります:1.AIDLの関連クラスを導入する.2.aidlで生成するclassを呼び出す.
Androidの開発でプロセス間通信を実現する具体的な手順は以下の通りです.
1、AIDLファイルを作成して、このファイルの中でインタフェースを定義して、このインタフェースはクライアントがアクセスできる方法と属性を定義します.例えば、ITaskBinder.adil
package com.cmcc.demo;
import com.cmcc.demo.ITaskCallback;
interface ITaskBinder {
    boolean isTaskRunning();
    void stopRunningTask(); 
    void registerCallback(ITaskCallback cb); 
    void unregisterCallback(ITaskCallback cb);
}

ここで、ITaskCallbackはファイルITaskCallbackにある.aidlで定義:
package com.cmcc.demo;
interface ITaskCallback {
    void actionPerformed(int actionId);
}

注意:理論上、パラメータは基本データ型とString、そしてBundleの派生クラスを伝達することができるが、Eclipseでは現在のADTはBundleをパラメータとしてサポートしていない.Antでコンパイルできるというが、私は試していない.
2、Android開発中にAIDLファイルをコンパイルし、Antを使用すると手動が必要になる可能性があり、Eclipse pluginを使用すると、adilファイルに基づいてjavaファイルを自動生産してコンパイルすることができ、人為的な介入を必要としない.
3.Javaファイルにおいて、AIDLで定義インタフェースを実現する.コンパイラはAIDLインタフェースに基づいてJAVAインタフェースを生成します.このインタフェースにはStubという内部抽象クラスがあり、インタフェースを拡張し、リモートコールに必要ないくつかの方法を継承しています.次に、カスタマイズされたいくつかのインタフェースを自分で実現する必要があります.
ITaskBinder.aidlでのインタフェースの実装はMyServices.JAvaでインタフェース内にクラスを埋め込む方式を実現する:
private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {
        public void stopRunningTask() {
            //@TODO
        }

        public boolean isTaskRunning() {
            //@TODO
            return false;
        }

        public void registerCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.register(cb);
        }

        public void unregisterCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.unregister(cb);
        }
};

MyActivity.JAvaのITaskCallback.aidlインタフェースの実装:
private ITaskCallback mCallback = new ITaskCallback.Stub() {
        public void actionPerformed(int id) {
          //TODO
         printf("callback id=" + id);
        }
};

4.クライアントにインタフェースITaskBinderを提供し、サービスと書かれている場合、そのサービスを拡張し、onBind()メソッドを再ロードして、上記のインタフェースを実装するクラスのインスタンスを返す.この場所で返されるmBinderは、上に定義が埋め込まれているものです.(MyService.java)
    public IBinder onBind(Intent t) {
        printf("service on bind");
        return mBinder;
    }

Activityでは、Binderで定義インタフェースによりリモートコールを行うことができる.
5.サーバ側でクライアントの関数をコールバックする.クライアントが取得したIBinderインタフェースの場合、コールバック関数を登録することを前提としています.これにより、サーバ側は呼び出した関数がMyServicesであることを知っています.JAva:
    void callback(int val) {
        final int N = mCallbacks.beginBroadcast();
        for (int i=0; i <N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).actionPerformed(val);
            } catch (RemoteException e) {
                // The RemoteCallbackList will take care of removing
                // the dead object for us.
            }
        }
        mCallbacks.finishBroadcast();
    }