2010-02-22 16 views
59

Ho implementato un BroadcastReceiver che viene attivato da AlarmManager. AlarmManager è inizializzato su BOOT_COMPLETED. Quindi devo dichiarare il ricevitore nel manifest.Come determinare se una delle mie attività è in primo piano

Il mio problema è che voglio che BroadcastReceiver faccia qualcosa quando nessuna delle mie attività è in primo piano (ovvero l'utente non sta interagendo con la mia applicazione). Estraggo le informazioni da un server remoto e non voglio avvisare l'utente se è attualmente nella mia applicazione comunque.

Finora non sono riuscito a trovare un modo per determinare se la mia applicazione è in primo piano. C'è un modo per fare una cosa del genere? ActivityManager mi dice se la mia applicazione è in esecuzione ma non se è in primo piano.

Il problema è praticamente la stessa di quella descritta qui: Inform Activity from a BroadcastReceiver ONLY if it is in the foreground

SOLUZIONE:

Dopo aver valutato diverse soluzioni voglio delineare rapidamente quello che penso sia il metodo migliore per affrontare le attività nel sfondo/primo piano.

Il modo migliore è registrare un ricevitore di trasmissione nel metodo onResume della propria attività e cancellarlo dalle attività su onPause. Qualsiasi servizio o altro elemento di sfondo sarà necessario inviare un intent broadcast con un'azione specifica che intercetterà l'attività dell'utente.

Se la tua attività è in primo piano avrà il suo destinatario registrato registrato ed è in grado di gestire direttamente l'invio di intento dal tuo servizio. Se non è in primo piano, non riceverà l'intento, ma il servizio che ha invocato la trasmissione saprà che nessuno ha intercettato il suo intento di trasmissione e sarà in grado di gestirlo da solo. Ad esempio, si potrebbe di avviare l'attività desiderata, mostrare una notifica ecc

+5

"il servizio che ha invocato la trasmissione saprà che nessuno stato intercettato il suo intento broadcast" - forse una domanda stupida, ma come farà a saperlo? – ostergaard

+0

@ajostergaard Penso che vada così: Broadcast inviato "sei in foregraund" intento. Quando Activity è in primo piano, può ricevere quell'intenzione (poiché registra il proprio recevier in onResume) e rispetta con Intent "sì, sono in primo piano". Broadcast può revevie che, quindi conoscere lo stato di attività. BTW. Controlla la mia risposta per questa domanda di seguito :) – mklimek

risposta

12

La vostra attività in grado di monitorare il proprio stato come se sia in primo piano (booleano insieme a true in onStart(), a false in onStop()). Ahimè, quel booleano non ti viene fornito automaticamente da Activity.

+0

Sarebbe possibile ma tutte le attività nella mia applicazione supportano tale scenario. Inoltre non voglio accoppiare questo comportamento alle mie attività, ma piuttosto che BroadcastReceiver determini lo stato attuale. – Moritz

+1

False, è possibile eseguire lo sfondo di un'attività senza che venga chiamato 'onStop()'. Leggi questo: http://developer.android.com/reference/android/app/Activity.html –

+0

@ JorgeFuentesGonzález: Si prega di citare un passaggio specifico in quella pagina che esegue il backup delle richieste. – CommonsWare

4

ActivityManager#getRunningAppProcesses() restituisce un elenco di RunningAppProcessInfo. Ogni RunningAppProcessInfo ha un campo chiamato importanza. l'importanza pari a RunningAppProcessInfo.IMPORTANCE_FOREGROUND sembra indicare quale attività viene attivamente osservata dall'utente. C'è anche RunningAppProcessInfo.IMPORTANCE_VISIBLE che è più basso, ma potrebbe valerne la pena.

+0

Grazie. Lo esaminerò. – Moritz

+0

Dopo aver esaminato le possibilità di RunningAppProcess, si è scoperto che l'importanza dei processi non cambia mai. Per la mia attività l'importanza è sempre stata IMPORTANCE_FOREGROUND (100). Applicato quando le attività non sono state avviate, l'attività è attiva in primo piano o lo stack delle attività viene inviato sul retro. Nessuna modifica nel valore di importanza. Quindi purtroppo questa non è una soluzione per il mio problema. :(Qualche altra idea? – Moritz

+0

Ho provato ad avviare uno dei miei progetti e ne ho spuntato un altro sopra e quello sullo sfondo è andato a IMPORTANCE_BACKGROUND (400). Sembra solo mostrare il nome del pacchetto dell'intero progetto come Bene, il tuo servizio fa parte del pacchetto che stai cercando di verificare? Forse avere il debugger collegato sta aumentando l'importanza o qualcosa del genere – jqpubliq

26

La seguente risposta: "Is application running in background", riepiloga le soluzioni disponibili per il controllo sfondo/foreground.

Nota:
In precedenza questa risposta suggerisce di utilizzare ActivityManager.getRunningAppProcesses(), tuttavia, che il metodo sembra essere non del tutto affidabile e il suo utilizzo è scoraggiato. Controlla il link sopra per i dettagli.

3

Ho implementato un BroadcastReceiver che viene attivato da AlarmManager. AlarmManager è inizializzato su BOOT_COMPLETED. Quindi devo dichiarare il ricevitore nel manifest.

Il mio problema è che voglio che BroadcastReceiver faccia qualcosa quando nessuna delle mie attività è in primo piano (ovvero l'utente non sta interagendo con la mia applicazione). Estraggo le informazioni da un server remoto e non voglio avvisare l'utente se è attualmente nella mia applicazione comunque.

Finora non sono riuscito a trovare un modo per determinare se la mia applicazione è in primo piano. C'è un modo per fare una cosa del genere? ActivityManager mi dice se la mia applicazione è in esecuzione ma non se è in primo piano.

Non sembra essere un modo diretto per determinare se una delle attività è l'attività in primo piano corrente in esecuzione. Tuttavia, è possibile ottenere l'effetto desiderato utilizzando una trasmissione ordinata e due ricevitori broadcast. Un ricevitore broadcast deve essere registrato su OnResume() e non registrato su OnPause(). Il secondo destinatario della trasmissione verrà dichiarato nel manifest come hai già fatto. Imposta l'androide: priorità per i tuoi ricevitori in modo tale che se il ricevitore registrato dinamicamente è registrato, riceverà prima l'intento, quindi potrai mangiare l'intento in modo che il destinatario della trasmissione che hai registrato nel tuo manifest non venga mai informato.

+0

Il ricevitore di trasmissione ordinato sembra una buona soluzione che è degna di essere provata. – TieDad

1

Vorrei usare ActivityLifecycleCallbacks per ottenere una soluzione molto più pulita.

E può essere insicuro, leggere this prima di decidere di usare l'esempio di seguito in produzione. Funziona in 'sviluppo domestico' per il mio dispositivo e la versione 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; 
} 

Registrati App in AndroidManifest:

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

E il pezzo finale del puzzle:

public class YourReceiver extends BroadcastReceiver { 

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