Domanda

Sto cercando di controllare a distanza una carta da parati dal vivo da un widget. Sono nella stessa APK, ma ovviamente diversi processi. Chiamare un "" attività" della carta da parati dal vivo è di scarsa utilità per me dal momento che è un processo diverso. Il widget ha semplici pulsanti che, se premuti,

Così che (credo) ho bisogno è IPC e AIDL.

Per prima cosa ho creato l'AIDL sul lato carta da parati, che ha lavorato bene. Ha tre metodi e non parametri aggiuntivi. Ma quando ho aggiunto il lato client al widget, ho ottenuto un errore che mi dice che non può legarsi a tale interfaccia remota perché il widget è già un BroadcastListener. Ho cercato di ottenere la movimentazione pulsante senza bisogno del Widget per essere un BroadcastListener, ma che sembra essere impossibile.

Beh nessun problema, giusto? Ho appena creato un servizio ai widget che si lega ai interfaccia remota, perché mentre il widget è un BroadcastListener, il servizio non è, e tutto dovrebbe andare bene.

O almeno così ho pensato.

Bene, sto ottenendo i pulsanti del widget per attivare il servizio di widget. Il legame con le rese di servizi remoti me il seguente avviso:

Impossibile avviare il servizio Intent (act = com.blabla.IRemoteService):. Non trovato

Sto usando getApplicationContext () all'interno del servizio del widget di legarsi al roba remoto. Io ho il servizio widget nel manifesto, ma non ho il servizio remoto in là. Quando mi metto in là, ho un InstantiationException non specifico.

In Service onStart del Widget () che sto facendo questo:

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

Ho anche ...

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

La mia domanda è questa: Qualcuno ha fatto mai successo una chiamata remota da un widget in un'altra applicazione? Considerando Sto parlando di una carta da parati dal vivo qui, e il fatto che io non sono interessato a chiamare un'attività all'interno delle chiamate di processo widget di funzione, ma causa all'interno della carta da parati dal vivo, quali opzioni devo diverso da IPC, se del caso?

E se IPC è il modo di andare qui, quello che sto facendo di sbagliato?

È stato utile?

Soluzione

Ho trovato la risposta alla mia domanda. Per rendere le cose più facili per gli altri, ecco la soluzione:

Quando si effettua un servizio remoto, si deve scrivere l'AIDL che verrà compilato in una sorta di interfaccia stub, l'implementazione di tale interfaccia (cioè il codice che viene eseguito quando qualcuno chiama i metodi remoti), e una classe che estende "Servizio", che restituisce la classe di implementazione nel metodo onBind (). (Un servizio locale normale sarebbe restituire null in quel metodo)

Ora quello che non avevo capito è che si deve avere una definizione di servizio nel manifesto - CON FILTRO INTENT

Diciamo che la vostra AIDL si chiama IRemoteService.aidl, allora avete una classe chiamata RemoteService che assomiglia a questo:

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

Nel vostro manifesto Android, si desidera che questo:

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

Si noti il ??nome del servizio: si tratta di "RemoteService", non "IRemoteService" o anche "RemoteServiceImpl". È necessario il nome della classe che estende "Service", il cui metodo onBind andiamo a sovrascrivere.

Per completare la cosa, ecco il codice sul lato client -e sì, questo codice funziona anche da un altro servizio, ad esempio quella di partenza dal tuo widget;)

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

... dove RemoteServiceConnection può essere una classe interna in questo modo:

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

E ora, sei libero di chiamare ..

mService.remoteDetonateBirthdayCake();

In sintesi: Assicuratevi di avere una strofa di servizio nel manifesto Android, set "nome" al che restituisce l'effettiva attuazione nella sua onBind () metodo di classe, e si deve anche avere un filtro intenti con un definiton un'azione che punti all'interfaccia AIDL.

Suggerimento:. Se si chiama servizi remoti da un'applicazione all'interno di un APK diverso, aggiungere un elemento di "categoria" al filtro intento troppo, e impostarlo su DEFAULT

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top