2011-01-11 6 views
4

私はウィジェットからライブ壁紙をリモートコントロールしようとしています。彼らは同じAPKに入っていますが、明らかに異なるプロセスです。ライブ壁紙の「活動」を呼び出すことは、別のプロセスであるため、ほとんど役に立たない。ウィジェットには簡単なボタンがあり、押すと、ウィジェット/ローカルサービスからAndroidリモートサービス(IPC)を呼び出すにはどうすればいいですか?

私はIPCとAIDLが必要です。

私は壁紙側にAIDLを作成しましたが、うまくいきました。余分なパラメータを持たない3つの方法があります。しかし、クライアント側をウィジェットに追加すると、ウィジェットがすでにブロードキャスト・リスナーであるため、リモート・インターフェースにバインドできないというエラーが表示されます。私は、WidgetをBroadcastListenerにする必要なく、ボタン操作を取得しようとしましたが、これは不可能なようです。

問題はありません。ウィジェットがブロードキャスト・リスナーである一方、サービスはそうではなく、すべてがうまくいくはずなので、リモート・インターフェースにバインドするサービスをウィジェット内に作成しました。

そう思った。

さて、私はウィジェットのボタンを取得してウィジェットサービスを起動しています。リモートサービスにバインドすると、次の警告が表示されます。

サービスを開始できませんでした。Intent(act = com.blabla.IRemoteService):見つかりません。

私はリモートスタッフにバインドするためにウィジェットのサービス内でgetApplicationContext()を使用しています。マニフェストにウィジェットサービスがありますが、そこにリモートサービスはありません。私がそこに置くと、私は非特異的なInstantiationExceptionを取得します。ウィジェットのサービスONSTART()で

は、私はこれをやっている:

getApplicationContext().bindService(new Intent(IWallpaperRemote.class.getName()), 
    mConnection, Context.BIND_AUTO_CREATE); 

私も持っている...

private ServiceConnection mConnection = new ServiceConnection() { 
    public void onServiceConnected(ComponentName className, 
      IBinder service) { 
     mService = IWallpaperRemote.Stub.asInterface(service); 
     isBound = true; 
     Log.i("WidgetServiceConnection", "binding to service succeeded"); 
    } 

    public void onServiceDisconnected(ComponentName className) { 
     mService = null; 
     isBound = false; 
     Log.i("WidgetServiceConnection", "binding to service lost!"); 
    } 
}; 

私の質問はこれです:誰もが今までに成功し、リモート呼び出しからを行っています別のアプリケーションへのウィジェットですか?私はここでライブ壁紙について話していると思いますし、ウィジェットプロセス内でアクティビティを呼び出すことに関心がなく、ライブ壁紙内で関数呼び出しを行うことに興味があるという事実を考えれば、IPC以外のオプションはありますか?

ここに行く方法がIPCなら、どうしたらいいですか?

+0

〜 "彼らは同じAPKに入っていますが、明らかに異なるプロセスです。"同じAPKにいる場合は、別々のプロセスにする必要はありません。 –

+1

AFAIKでは、ウィジェットをライブ壁紙にすることはできません。これはどのように機能しますか? – Toumal

答えて

13

私自身の質問に対する答えが見つかりました。

リモートサービスを行う場合、コンパイルされるAIDLをスタブインタフェースの一種、そのインタフェースの実装(つまり実行されるコード)に書き込む必要があります。誰かがリモートメソッドを呼び出すとき)、およびonBind()メソッドの実装クラスを返す "Service"を継承するクラスです。 (通常のローカルサービスはそのメソッドでnullを返します)

ここで私が理解していなかったのは、マニフェストにサービス定義がなければならないということです。

あなたのAIDLはIRemoteServiceと呼ばれています。AIDL、その後、あなたはこのようになりますRemoteServiceというクラスがあります。

<service android:name="RemoteService"> 
    <intent-filter> 
     <action android:name="com.sofurry.favorites.IRemoteService"></action> 
</intent-filter> 
</service> 

注意サービス名:それは「、 "RemoteService" IRemoteServiceではありませんAndroidマニフェストで

public class RemoteService extends Service { 
    public IBinder onBind(Intent intent) { 
    Log.i("RemoteService", "onBind() called"); 
    return new RemoteServiceImpl(); 
    } 
    /** 
    * The IRemoteInterface is defined through IDL 
    */ 
    public class RemoteServiceImpl extends IRemoteService.Stub { 
    public void remoteDetonateBirthdayCake() throws RemoteException { 
     //your code here 
    } 
    }; 
} 

を、あなたはこれをしたいです"または" RemoteServiceImpl "でさえあります。 onBindメソッドがオーバーロードされた "Service"を継承するクラスの名前が必要です。

事を完了するために、ここでは、クライアント側のコードだ - そしてはい、このコードはまた、別のサービスの中から作品、たとえば1のためにあなたがあなたのウィジェットから起動;)

IRemoteService mService; 
RemoteServiceConnection mConnection = new RemoteServiceConnection(); 
getApplicationContext().bindService(new Intent(IRemoteService.class.getName()), mConnection, Context.BIND_AUTO_CREATE); 

...どこRemoteServiceConnectionそのような内部クラスになります

class RemoteServiceConnection implements ServiceConnection { 
    public void onServiceConnected(ComponentName className, 
     IBinder service) { 
     mService = IRemoteService.Stub.asInterface(service); 
     isBound = true; 
    } 

    public void onServiceDisconnected(ComponentName className) { 
     mService = null; 
     isBound = false; 
    } 
}; 

そして今、あなたが呼び出すのは自由ですが...

mService.remoteDetonateBirthdayCake(); 

要約:アンドロイド・マニフェストにサービス・スタンザがあることを確認し、onBind()メソッドで実際の実装を戻すクラスに "name"を設定します。また、そのポイントで定義されたアクションを持つインテント・フィルターも必要ですAIDLインタフェースに送信する。

ヒント:別のAPK内のアプリからリモートサービスを呼び出す場合は、インテントフィルタにも「カテゴリ」要素を追加してDEFAULTに設定します。

+3

+1素敵な書き込み –

+0

こんにちは..私にあなたのサンプルアプリケーションを送ることができます..または私の答えを与えるようにしてください... http://stackoverflow.com/questions/11116614/android-ipc-remote-service -call-display-error – NovusMobile

+1

注:Android Studioの場合、AIDLファイルは新しい場所にあります: "./app/src/main/aidl/ ..."(参照するクラスと同じパッケージ階層とファイルが一致している必要があります) String(またはプリミティブ)ではないAIDLを通過するすべてのクラス/タイプは、Parcelableインターフェイスを実装する必要があります(使用されている場合は、Javaのインポートと同様に他のAIDLファイルにインポートされます)。また、AIDLはXML/Javaの前に解析され、エラーのデバッグメッセージは大幅に改善される可能性があります。しかし、一度あなたがそれらのクラス分け可能クラスを設定したら、私はこれをIPCを行うための最良の方法と見なします(さらに、統合テストも十分にカバーされています) – mawalker

関連する問題