Frage

Ich versuche, Remote zu steuern, um ein Live-Wallpaper von einem Widget. Sie sind in der gleichen APK, aber offensichtlich unterschiedliche Prozesse. eine „Aktivität“ des Live-Wallpapers Aufruf ist wenig hilfreich für mich, da es ein anderes Verfahren ist. Das Widget hat einfache Tasten, die, wenn sie gedrückt wird,

Also, was (ich glaube) ich brauche, ist IPC und AIDL.

Zuerst habe ich geschaffen, um die AIDL auf der Tapete Seite, die gut funktioniert. Es verfügt über drei Methoden ohne zusätzliche Parameter. Aber wenn ich die client zum Widget hinzugefügt, bekam ich einen Fehler mir zu sagen, dass ich nicht auf diese Remote-Schnittstelle binden kann, weil das Widget bereits ein Broadcast ist. Ich versuchte Taste Handhabung immer in, ohne das Widget zu benötigen ein Broadcast zu sein, aber das scheint unmöglich zu sein.

Nun kein Problem, nicht wahr? Ich habe gerade einen Dienst innerhalb des Widgets erstellt, dass bindet an die Remote-Schnittstelle, denn während das Widget ein Broadcast ist, ist der Dienst nicht, und alles in Ordnung sein sollte.

oder so dachte ich.

Nun, ich bin immer die Tasten des Widget den Widget-Service auszulösen. Die Bindung an den Remote-Service bringt mir die folgende Warnung:

Dienst kann nicht Absicht starten (act = com.blabla.IRemoteService.): Nicht gefunden

Ich bin mit getApplicationContext () im Dienst des Widgets zu binden an die Remote-Sachen. Ich mache den Widget-Service im Manifest, aber ich habe nicht den Remote-Service in dort habe. Wenn ich es dort setzen Sie, ich habe eine nicht-spezifische InstantiationException erhalten.

In der Service-onStart Widget () Ich tue dies:

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

Ich habe auch ...

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!");
    }
};

Meine Frage ist diese: Hat jemand schon einmal erfolgreich ein Ferngespräch von einem Widget in einer anderen Anwendung getan? Bedenkt, dass ich über eine Live-Wallpaper Die Rede ist hier, und die Tatsache, dass ich nicht daran interessiert bin eine Aktivität innerhalb des Widgets Prozess aber Ursache Funktionsaufrufe innerhalb der Live-Wallpaper in Aufrufen, welche Möglichkeiten habe ich andere haben als IPC, wenn überhaupt?

Und wenn IPC ist der Weg hier zu gehen, was mache ich falsch?

War es hilfreich?

Lösung

fand ich die Antwort auf meine eigene Frage. Um die Dinge einfacher für andere, hier ist die Lösung:

Wenn Sie einen Remote-Service zu tun, hat man die AIDL zu schreiben, die in eine Art Stub-Schnittstelle kompiliert werden, die Umsetzung dieser Schnittstelle (dh den Code, der ausgeführt wird, wenn jemand die Remote-Methoden aufruft) und eine Klasse, erweitert „Service“, die die Implementierungsklasse in der onBind () Methode gibt. (Ein normaler lokaler Dienst würde null in diesem Verfahren zurück)

Nun, was hatte ich nicht verstanden ist, dass Sie eine Service-Definition im Manifest haben muss - mit der Absicht, FILTER

Lassen Sie uns sagen, dass Ihre AIDL IRemoteService.aidl genannt wird, dann haben Sie eine Klasse namens Remoteservice, die wie folgt aussieht:

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
    }
  };
}

In Ihrem Android-Manifest, Sie wollen diese:

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

Beachten Sie den Namen des Dienstes: Es ist „Remoteservice“, nicht „IRemoteService“ oder sogar „RemoteServiceImpl“. Sie müssen den Namen der Klasse, die „Service“, dessen onBind Methode, die wir overrode.

erstreckt

, um die Sache abzuschließen, hier ist der Code auf der Client-Seite -und ja diesen Code funktioniert auch aus einem anderen Dienst, zum Beispiel, das Sie von Ihrem Widget gestartet;)

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

... wo RemoteServiceConnection kann eine innere Klasse sein wie so:

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;
    }
};

Und jetzt bist du frei ..

nennen
mService.remoteDetonateBirthdayCake();

Fazit: Achten Sie darauf, einen Dienst Strophe im Android Manifest haben, set „name“ auf die Klasse, dass die Renditen der tatsächliche Implementierung in seiner onBind () -Methode, und Sie müssen auch einen Intent-Filter mit einer Aktion definiton haben, dass verweist auf die AIDL Schnittstelle.

. Hinweis: Wenn Sie Remote-Dienste von einer App innerhalb einer anderen APK fordern, fügen Sie ein „Kategorie“ Element der Intent-Filter zu, und setzen Sie sich auf DEFAULT

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top