2010-02-22 15 views
59

Implementé un BroadcastReceiver que es activado por el AlarmManager. El AlarmManager se inicializa en BOOT_COMPLETED. Entonces tengo que declarar el receptor en el manifiesto.Cómo determinar si una de mis actividades está en primer plano

Mi problema es que quiero que el BroadcastReceiver solo haga algo cuando ninguna de mis actividades está en primer plano (también conocido como el usuario no está interactuando con mi aplicación). Extraigo información de un servidor remoto y no quiero notificar al usuario si está actualmente en mi aplicación.

Hasta ahora no he logrado encontrar una manera de determinar si mi aplicación está en primer plano. ¿Hay alguna manera de hacer tal cosa? El ActivityManager me dice si mi aplicación se está ejecutando, pero no si está en primer plano.

El problema es más o menos el mismo que se describe aquí: Inform Activity from a BroadcastReceiver ONLY if it is in the foreground

SOLUCIÓN:

Después de evaluar varias soluciones quiero esbozar rápidamente lo que creo que es el mejor método para hacer frente a las actividades en el fondo, frente.

La forma preferida es registrar un receptor de difusión en el método onResume de su actividad y anular el registro en las actividades en onPause. Cualquier servicio u otro elemento de fondo tendrá que enviar un intento de difusión con una acción específica que su actividad interceptará.

Si su actividad está en primer plano, tendrá su receptor de intención registrado y podrá tratar directamente con el intento de envío de su servicio. Si no está en primer plano, no recibirá el intento, pero el servicio que invocó la transmisión sabrá que nadie ha interceptado su intento de transmisión y podrá tratarlo por sí mismo. Por ejemplo, que se podría poner en marcha la actividad deseada, mostrar una notificación etc.

+5

"el servicio que invoca la emisión sabrá que nadie interceptado su intención de difusión" - posiblemente una pregunta estúpida, pero ¿cómo lo sabrá? – ostergaard

+0

@ajostergaard Creo que es así: la difusión envió el intento "¿Estás en foregraund"? Cuando la actividad está en primer plano, puede recibir esa intención (porque registra el recevier propio en el resultado) y responde con el intento "sí, estoy en primer plano". La difusión puede revelar eso, así conocer el estado de la actividad. Por cierto. Compruebe mi respuesta para esta pregunta a continuación :) – mklimek

Respuesta

12

Su actividad se puede realizar un seguimiento de su propio estado en cuanto a si está en el primer plano (conjunto booleano para true en onStart(), a false en onStop()). Por desgracia, ese booleano no se le proporciona por Activity automáticamente.

+0

Eso sería posible, pero cada actividad en mi aplicación sería compatible con ese escenario. Además, no quiero vincular este comportamiento con mis actividades, sino que el BroadcastReceiver determine el estado real. – Moritz

+1

False, una actividad puede estar en segundo plano sin que se llame a 'onStop()'. Lea esto: http://developer.android.com/reference/android/app/Activity.html –

+0

@ JorgeFuentesGonzález: Indique un pasaje específico en esa página que respalda sus reclamos. – CommonsWare

4

ActivityManager#getRunningAppProcesses() devuelve una lista de RunningAppProcessInfo. Cada RunningAppProcessInfo tiene un campo llamado importancia. una importancia igual a RunningAppProcessInfo.IMPORTANCE_FOREGROUND parece mostrar qué actividad está siendo observada activamente por el usuario. También hay RunningAppProcessInfo.IMPORTANCE_VISIBLE que es más bajo, pero podría valer la pena echarle un vistazo.

+0

Gracias. Voy a investigar eso. – Moritz

+0

Después de investigar las posibilidades de RunningAppProcess, resultó que la importancia de los procesos nunca cambia. Para mi actividad, la importancia siempre ha sido IMPORTANCE_FOREGROUND (100). Eso se aplica cuando las actividades no se han iniciado en absoluto, la actividad está activa en primer plano o la pila de actividades se envía a la parte posterior. Sin cambios en el valor de importancia. Por desgracia, esta no es una solución para mi problema. :(¿Alguna otra idea? – Moritz

+0

Intenté poner en marcha uno de mis proyectos y luego colocar otro encima y el que estaba en el fondo fue a IMPORTANCE_BACKGROUND (400). Parece que solo muestra el nombre del paquete de todo el proyecto como Bueno, ¿su servicio es parte del paquete que está tratando de verificar? Tal vez tener el depurador conectado es elevar la importancia o algo así. – jqpubliq

26

La siguiente respuesta: "Is application running in background", resume las soluciones disponibles para la verificación de fondo/primer plano.

Nota:
Anteriormente esta respuesta sugiere utilizar ActivityManager.getRunningAppProcesses(), sin embargo, que el método parecía ser no del todo fiable y su uso no se recomienda. Verifique el enlace de arriba para los detalles.

3

He implementado un BroadcastReceiver que se activa mediante el AlarmManager. El AlarmManager se inicializa en BOOT_COMPLETED. Entonces tengo que declarar el receptor en el manifiesto.

Mi problema es que quiero que el BroadcastReceiver solo haga algo cuando ninguna de mis actividades está en primer plano (también conocido como el usuario no está interactuando con mi aplicación). Extraigo información de un servidor remoto y no quiero notificar al usuario si está actualmente en mi aplicación.

Hasta ahora no he logrado encontrar una manera de determinar si mi aplicación está en primer plano. ¿Hay alguna manera de hacer tal cosa? El ActivityManager me dice si mi aplicación se está ejecutando, pero no si está en primer plano.

No parece haber una manera directa de determinar si una de sus actividades es la actividad de primer plano en ejecución. Sin embargo, puede obtener el efecto deseado mediante el uso de una transmisión ordenada y dos receptores de difusión. Un receptor de difusión debe estar registrado en OnResume() y no registrado en OnPause(). El segundo receptor de difusión se declarará en su manifiesto como ya lo hizo. Establezca el android: prioridad para sus receptores de modo que si el receptor registrado dinámicamente está registrado, primero recibirá el intento, luego puede comer el intento para que nunca se notifique al receptor de difusión que registró en su manifiesto.

+0

El receptor de difusión ordenado parece una buena solución que vale la pena intentar. – TieDad

1

Usaría ActivityLifecycleCallbacks para obtener una solución mucho más limpia.

puede ser inseguro, lea this antes de decidirse por utilizar el siguiente ejemplo en producción. Funciona en 'desarrollo del hogar' para mi dispositivo y la versión del sistema operativo.

public class App extends Application implements Application.ActivityLifecycleCallbacks { 

private boolean inForeground; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    registerActivityLifecycleCallbacks(this); 
} 

@Override 
public void onActivityResumed(Activity activity) { 
    inForeground = activity instanceof YourActivity; 
} 

public boolean isInForeground() { 
    return inForeground; 
} 

Registro App en AndroidManifest:

<application 
     android:name=".App" /> 

y la pieza final del rompecabezas:

public class YourReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     App app = (App) context.getApplicationContext(); 
     if(app.isInForeground()){ 
      // do some stuff 
     } 
    } 
} 
Cuestiones relacionadas