Pregunta

Estoy tratando de controlar a distancia un fondo de pantalla en vivo desde un widget. Están en la misma APK, pero obviamente diferentes procesos. Llamar a una "actividad" de la pantalla en vivo es de poca utilidad para mí, ya que es un proceso diferente. El widget tiene botones simples que, cuando se pulsa,

Así que lo que (creo) que necesito es IPC y AIDL.

Primero creé el AIDL en el lado del papel pintado, que funcionaba bien. Tiene tres métodos sin parámetros adicionales. Pero cuando he añadido el clientside al widget, recibí un error que me dice que no puede unirse a la interfaz remota porque el widget es ya un BroadcastListener. He intentado conseguir en gestión con el botón sin necesidad del Widget a ser un BroadcastListener, pero que parece ser imposible.

Bueno, no hay problema, ¿verdad? Acabo de crear un servicio dentro del widget que se une a la interfaz remota, porque mientras que el widget es un BroadcastListener, el servicio no es, y todo debería estar bien.

O eso creía yo.

Bueno, yo estoy poniendo los botones del widget para activar el servicio de widget. La unión a los rendimientos de servicio remoto mí la siguiente advertencia:

No se puede iniciar el servicio Intención (act = com.blabla.IRemoteService):. No se ha encontrado

Estoy utilizando getApplicationContext () dentro del servicio del widget que se unen a las cosas a distancia. Tengo el widget en el manifiesto, pero no tengo el servicio remoto en ese país. Cuando me puse allí, consigo un InstantiationException no específica.

En Servicio onStart del Widget () Estoy haciendo esto:

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

También he ...

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

Mi pregunta es la siguiente: ¿Alguien ha hecho alguna vez con éxito una llamada remota desde un widget en otra aplicación? Teniendo en cuenta que estoy hablando de un fondo de pantalla en vivo aquí, y el hecho de que no estoy interesado en llamar a una actividad dentro del proceso de widget de la función, pero causa llamadas dentro de la pantalla en vivo, ¿qué opciones tengo aparte de IPC, en su caso?

Y si el IPC es el camino a seguir aquí, ¿qué estoy haciendo mal?

¿Fue útil?

Solución

He encontrado la respuesta a mi propia pregunta. Para facilitar las cosas para los demás, aquí está la solución:

Cuando se realiza un servicio remoto, uno tiene que escribir el AIDL que se compila en una especie de interfaz de talón, la aplicación de dicha interfaz (es decir, el código que se ejecuta cuando alguien llama a los métodos remotos), y una clase que se extiende "servicio" que devuelve la clase de implementación en el método onBind (). (A servicio local normal sería devolver null en ese método)

Ahora lo que yo no había entendido es que debe tener una definición de servicio en el manifiesto - CON FILTRO DE INTENCIÓN

Digamos que su AIDL se llama IRemoteService.aidl, entonces usted tiene una clase llamada RemoteService que tiene este aspecto:

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

En su manifiesto de Android, desea que esta:

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

Tenga en cuenta el nombre del servicio: Se trata de "RemoteService", no "IRemoteService" o incluso "RemoteServiceImpl". Se necesita el nombre de la clase que se extiende "servicio", cuyo método onBind overrode nos.

Para completar la cosa, aquí está el código del lado del cliente -y sí, este código también funciona desde dentro de otro servicio, por ejemplo, uno se encontraba cuando empezó el widget;)

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

... donde RemoteServiceConnection puede ser una clase interna de este 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;
    }
};

Y ahora, usted es libre de llamar ..

mService.remoteDetonateBirthdayCake();

En resumen: Asegúrese de tener una estrofa servicio en el manifiesto de Android, sistema de "nombre" a la que vuelve la implementación real en su onBind () método de clase, y también debe tener un filtro intención con un definiton acción que puntos a la interfaz AIDL.

Consejo:. Si está llamando a los servicios remotos desde una aplicación dentro de un APK diferente, añadir un elemento de "categoría" al filtro intención también, y lo puso a DEFAULT

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top