web-dev-qa-db-fra.com

Comment déterminer si l'une de mes activités est au premier plan

J'ai implémenté un BroadcastReceiver qui est déclenché par AlarmManager. AlarmManager est initialisé sur BOOT_COMPLETED. Je dois donc déclarer le destinataire dans le manifeste.

Mon problème est que je veux que le BroadcastReceiver fasse seulement quelque chose quand aucune de mes propres activités n'est au premier plan (alias l'utilisateur n'interagit pas avec mon application). Je tire des informations d'un serveur distant et je ne veux pas informer l'utilisateur s'il est actuellement dans mon application.

Jusqu'à présent, je n'ai pas réussi à trouver un moyen de déterminer si ma demande est au premier plan. Existe-t-il un moyen de faire une telle chose? ActivityManager me dit si mon application est en cours d'exécution mais pas si elle est au premier plan.

Le problème est à peu près le même que celui décrit ici: Informer l'activité d'un BroadcastReceiver UNIQUEMENT s'il est au premier plan

SOLUTION:

Après avoir évalué plusieurs solutions, je veux décrire rapidement ce que je pense être la meilleure méthode pour gérer les activités en arrière-plan/au premier plan.

La manière préférée est d'enregistrer un récepteur de diffusion dans la méthode onResume de votre activité et de le désenregistrer sur les activités sur onPause. Tout service ou autre élément d'arrière-plan devra alors envoyer une intention de diffusion avec une action spécifique que votre activité interceptera.

Si votre activité est au premier plan, son destinataire sera enregistré et pourra traiter directement l'intention envoyée par votre service. S'il n'est pas au premier plan, il ne recevra pas l'intention, mais le service qui a invoqué la diffusion saura que personne n'a intercepté son intention de diffusion et sera en mesure de gérer cela lui-même. Par exemple, il pourrait alors lancer l'activité souhaitée, afficher une notification, etc.

59
Moritz

La réponse suivante: " l'application s'exécute en arrière-plan ", résume les solutions disponibles pour la vérification de l'arrière-plan/du premier plan.

Remarque:
Auparavant, cette réponse suggérait d'utiliser ActivityManager.getRunningAppProcesses(), mais cette méthode ne semblait pas totalement fiable et son utilisation est déconseillée. Consultez le lien ci-dessus pour les détails.

27
Idolon

Votre activité peut suivre son propre état pour savoir si elle est au premier plan (définissez booléen sur true dans onStart(), sur false dans onStop()) . Hélas, ce booléen ne vous est pas fourni automatiquement par Activity.

12
CommonsWare

ActivityManager#getRunningAppProcesses() renvoie une liste de RunningAppProcessInfo. Chaque RunningAppProcessInfo a un champ appelé importance. importance égale à RunningAppProcessInfo.IMPORTANCE_FOREGROUND semble indiquer quelle activité est activement observée par l'utilisateur. Il y a aussi RunningAppProcessInfo.IMPORTANCE_VISIBLE qui est inférieur mais qui pourrait valoir le coup d'être vérifié.

4
jqpubliq

consultez ma solution pour déterminer si une activité est au premier plan: http://www.mannaz.at/codebase/Android-activity-foreground-surveillance/

Il devrait être facile de rétablir la logique de "au premier plan" à "pas au premier plan".

3
whlk

J'ai implémenté un BroadcastReceiver qui est déclenché par AlarmManager. AlarmManager est initialisé sur BOOT_COMPLETED. Je dois donc déclarer le destinataire dans le manifeste.

Mon problème est que je veux que le BroadcastReceiver fasse seulement quelque chose quand aucune de mes propres activités n'est au premier plan (alias l'utilisateur n'interagit pas avec mon application). Je tire des informations d'un serveur distant et je ne veux pas informer l'utilisateur s'il est actuellement dans mon application.

Jusqu'à présent, je n'ai pas réussi à trouver un moyen de déterminer si ma demande est au premier plan. Existe-t-il un moyen de faire une telle chose? ActivityManager me dit si mon application est en cours d'exécution mais pas si elle est au premier plan.

Il ne semble pas y avoir de moyen direct de déterminer si l'une de vos activités est l'activité de premier plan en cours d'exécution. Cependant, vous pouvez obtenir l'effet souhaité en utilisant une diffusion ordonnée et deux récepteurs de diffusion. Un récepteur de diffusion doit être enregistré dans OnResume () et non enregistré dans OnPause (). Le 2ème récepteur de diffusion sera déclaré dans votre manifeste comme vous l'avez déjà fait. Définissez Android: priorité pour vos récepteurs de sorte que si le récepteur enregistré dynamiquement est enregistré, il recevra d'abord l'intention, puis vous pourrez manger l'intention afin que le récepteur de diffusion que vous avez enregistré dans votre manifeste ne soit jamais informé.

3
Pastiche

J'utiliserais ActivityLifecycleCallbacks pour obtenir une solution beaucoup plus propre.

Il peut être incertain, lisez this avant de décider d'utiliser l'exemple ci-dessous en production. Il fonctionne en "développement domestique" pour mon appareil et la version de mon système d'exploitation.

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

Enregistrez App dans AndroidManifest:

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

Et la dernière pièce du 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
        }
    }
}
1
klimat

Vous pouvez tester si la fenêtre a le focus - mais comme indiqué dans les documents de développement, ce n'est pas la même chose que si l'activité est au premier plan.

1
surtyaar