5

異なるパッケージのいくつかのサービスで共通のオブジェクトを共有しようとしています。各サービスは同じオブジェクトを呼び出す必要があります。

たとえば、サービス A (APK A から) がカスタム オブジェクトをインスタンス化し、サービス B と C (APK B と C から) がこのオブジェクトの参照を取得して、そのメソッドを呼び出すようにしたいとします。

Android リファレンスで、 Parcelを使用することで可能であることがわかりました。

アクティブなオブジェクト

Parcel の珍しい機能は、アクティブなオブジェクトを読み書きできることです。これらのオブジェクトの場合、オブジェクトの実際の内容は書き込まれず、オブジェクトを参照する特別なトークンが書き込まれます。パーセルからオブジェクトを読み取るとき、オブジェクトの新しいインスタンスを取得するのではなく、最初に書き込まれたオブジェクトとまったく同じオブジェクトを操作するハンドルを取得します。使用可能なアクティブ オブジェクトには 2 つの形式があります。

Binder オブジェクトは、Android の一般的なクロスプロセス通信システムのコア機能です。IBinder インターフェイスは、Binder オブジェクトを使用して抽象プロトコルを記述します。そのようなインターフェースはすべてパーセルに書き込むことができ、読み取ると、そのインターフェースを実装する元のオブジェクト、または元のオブジェクトへの呼び出しを通信する特別なプロキシ実装のいずれかを受け取ります。使用するメソッドは、writeStrongBinder(IBinder)、writeStrongInterface(IInterface)、readStrongBinder()、writeBinderArray(IBinder[])、readBinderArray(IBinder[])、createBinderArray()、writeBinderList(List)、readBinderList(List)、createBinderArrayList() です。 .

AIDL を介してオブジェクト (バインダーを拡張する) を渡してこれを実行しようとしましたが、何も機能しません。メソッド createFromParcel(Parcel in) から参照を取得しようとすると、常に ClassCastException が発生します。

私のコードの例:

public class CustomObject extends Binder implements Parcelable {

  public CustomObject() {
    super();
  }

  public static final Parcelable.Creator<CustomObject> CREATOR = new Parcelable.Creator<CustomObject>() {
  public CustomObject createFromParcel(Parcel in) {
    IBinder i = in.readStrongBinder();
      // HOW TO RETRIEVE THE REFERENCE ??
      return null;
    }

    @Override
    public CustomObject[] newArray(int size) {
      return null;
    }
  };

  @Override
  public int describeContents() {
    return 0;
  }

  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeStrongBinder(this);
  }
}

誰かがすでにそれを行っていますか?

前もって感謝します !

4

3 に答える 3

2

ここに 2 つのアプローチがあります。

シンプル: オブジェクト自体に aidl を使用する

  • この「カスタム オブジェクト」をパーセルとして渡す既存の AIDL インターフェイスがあるようです。そうしないでください。その代わり:
  • 通過するオブジェクト自体が AIDL によって記述されている必要があります。たとえば、それを と呼ぶとしICustomObject.aidlます。
  • この場合、オブジェクトを Parcelable にする必要はありません。おそらく、上記のコードを記述する必要さえありません。AIDL で記述された型を別の型で使用するだけです。たとえば、次のような行をサービス A のメイン AIDL に追加します。

    ICustomObject getCustomObject();
    
  • サービス A では、Stub既に取得したクラス内で、単に から継承したものを返す必要がありますICustomObject

  • サービス B と C では、そのメソッドを呼び出すだけで を取得できますICustomObject。単純!小包はありません、いいえreadStrongBinder()、何もありません。

もっと強く

上記を実行すると、Android ツールチェーンは、オブジェクトをマーシャリングおよびアンマーシャリングする Java コードを生成します。代わりに、自分でコードを書くこともできます。

ICustomObject myObjectWhichActuallyLivesInAnotherProcess = ICustomObject.Stub.asInterface(parcel.readStrongBinder())

あるいは

ICustomObject myObjectWhichActuallyLivesInAnotherProcess = (ICustomObject)parcel.readStrongBinder().queryLocalInterface("com.your.custom.object");

しかし、私はあなたがすべてを助ければ、あなたの人生はより正気になると思います.

クラス分けの注意点

ICustomObject.aidlA、B、および C をビルドするプロジェクト間で結果のクラスを共有できるように、その中に含まれる Android の「ライブラリ プロジェクト」を作成することをお勧めします。

于 2013-05-27T17:28:03.320 に答える
0

これを自分でかなり広範囲に調べた後、実際に実行できるとは思いません。取得している ClassCastException は、BinderProxy(IBinder を拡張するプライベート クラス) を実際のクラス ( CustomObject) にキャストした結果です。ABinderProxyは、他のプロセス間で Binders を参照するときに常に渡されるように見えます。これは、「そのインターフェイスを実装する元のオブジェクトまたは特別なプロキシ実装のいずれか」を示すときに参照するオブジェクトです。では、 IBinderのメソッドBinderProxyを呼び出すことはできますが、それ以外はできません。onTransact()

「元のオブジェクト」がプロセス間で渡されると述べている場合、そのクラスのドキュメントには他にもいくつかのインスタンスが露骨にコピーアンドペーストされ、間違っているため、ドキュメントは正しくないと正直に思います。

于 2015-09-20T21:42:14.227 に答える
0

コンテンツプロバイダーを調べましたか?

于 2013-05-27T07:04:54.887 に答える