web-dev-qa-db-fra.com

Comment détecter les clics sur les boutons du système "Applications récentes" (Honeycomb +)

Je me demande quelle méthode ce bouton appelle.

enter image description here

Mon jeu se met toujours en pause/reprend correctement, sauf lorsque j'utilise ce bouton. Il semble que ce bouton n'appelle pas les méthodes onPause() et onResume() d'un Activity . Cela fonctionne si je quitte le jeu, allez dans une autre fenêtre (comme celle sur la photo), puis utilisez ce bouton pour reprendre. Mais si j'appuie simplement sur ce bouton, lorsque le jeu est en jeu, le jeu s'interrompt mais le thread ne reprend pas comme il le fait toutes les deux fois.

Difficile à expliquer mais j'espère être clair, sinon, demandez!

24
Green_qaue

Aucune des méthodes Activity Lifecycle standard n'est appelée lorsque le bouton "Applications récentes" est enfoncé. L'activité restera active après la liste des popups des applications récentes. Dans la partie gauche semi-transparente de cette liste, vous pouvez même observer que l'animation de l'application est toujours en cours d'exécution si vous exécutez un jeu avec une animation qui ne gère pas cette situation correctement. En fait, de nombreux jeux sur Google Play ne géraient pas cette situation correctement, même les meilleurs, comme Angry Birds.

La seule méthode Activity appelée lors de l'ouverture de la liste des applications récentes (ou à partir de celle-ci) est onWindowFocusChanged avec le paramètre booléen hasFocus. Lorsque l'utilisateur ouvre la liste de la méthode App récente onWindowFocusChanged() appelée avec hasFocus est égale à false et que la même méthode appelée avec hasFocus est égale à true lorsque l'utilisateur appuie sur Retour dans cette liste.

22
HitOdessit

Pour détecter quand le bouton 'Applications récentes' a été actionné, vous pouvez utiliser le service d'accessibilité. Vous devrez exécuter votre propre service d'accessibilité et recevoir des événements de type "TYPE_WINDOW_STATE_CHANGED" et vérifier le nom de la classe de l'événement.

  1. Lisez à propos de Accessibility Service in Android developer. Configurez votre propre service d'accessibilité, demandez la permission de l'utilisateur.
  2. Dans votre service d'accessibilité, remplacez la méthode onAccessibilityEvent()
  3. Dans cette méthode, vous recevrez l'objet AccessibilityEvent event, qui contient toutes les informations nécessaires sur un événement qui vient de se produire sur votre périphérique.
  4. Nous sommes intéressés par le ClassName. ClassName peut parfois être null alors n'oubliez pas! = Null check. Les noms de package de la fenêtre Applications récentes varient en fonction de la version d'Android:

    • Android 4.1: "com.Android.internal.policy.impl.RecentApplicationsDialog"
    • Android 4.2 - 4.4: "com.Android.systemui.recent.RecentsActivity"
    • Android 5.0 - 7.1: "com.Android.systemui.recents.RecentsActivity" (la lettre "s" a été ajoutée)

Je ne connais pas le nom de classe des appareils plus anciens, mais je ne pense pas que quelqu'un les conserve en 2017;)

Donc, vous aurez quelque chose comme ça:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || event.getClassName() == null) 
        return;

    String className = String.valueOf(event.getClassName());

    if (className.equals("com.Android.internal.policy.impl.RecentApplicationsDialog")
            || className.equals("com.Android.systemui.recent.RecentsActivity")
            || className.equals("com.Android.systemui.recents.RecentsActivity")){
        //Recent button was pressed. Do something.
    }
}

Je l'ai testé sur les appareils réels suivants: LG, Nexus, Sony et les appareils virtuels: Motorola, Samsung.

Si quelqu'un connaît une exception pour ces noms de classe, envoyez-moi un ping.

5
Kirill Karmazin

J'ai le même problème, j'ai résolu ce problème comme ci-dessous.er

Bouton Enregistrer, cliquez sur Diffuser pour Accueil et RecentApp

InnerReceiver mReceiver = new InnerReceiver();
IntentFilter mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mReceiver, mFilter);

Maintenant le code BroadcastReceiver

class InnerReceiver extends BroadcastReceiver {
    final String SYSTEM_DIALOG_REASON_KEY = "reason";
    final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            if (reason != null) {
                if (mListener != null) {
                    if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                        // Home Button click
                    } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                        // RecentApp or Overview Button click
                    }
                }
            }
        }
    }
}

Mais ne pas oublié de unregisterReceiver BroadcastReceiver

4
Lokesh

J'ai rencontré un problème similaire, donc, je devais savoir quand l'utilisateur appuierait sur le bouton des applications récentes (bouton de menu dans les anciennes versions d'Android). Après plusieurs heures de recherche, je n'ai trouvé aucun événement à saisir lorsque vous appuyez sur le bouton d'accueil ou sur le bouton de menu. j’ai trouvé qu’il fallait plus de temps pour appeler onStop () lorsque l’utilisateur appuyait sur le bouton d’accueil;

@Passer outre

public void onUserLeaveHint() {
    // do stuff
    super.onUserLeaveHint();
    userLeaveTime = System.currentTimeMillis() ;
    isNotPower = true;
}

@Passer outre

public void onStop() {
    super.onStop();
    if (isNotPower) {
        defStop = System.currentTimeMillis() - userLeaveTime;
        if (defStop > 200 ) {
            //home button
        }
        if (defStop < 200) {
            //recent apps button
        }
    }
    isNotPower = false;
}
  • le paramètre isNotPower qui vérifie que le bouton d'alimentation n'est pas enfoncé. Lorsque le bouton d'alimentation est enfoncé, la méthode onStop () est appelée mais pas onUserLeaveHint ().
3
khaled_alokby

La meilleure façon que j'ai trouvée est d'écouter l'action de diffusion intitulée "ACTION_CLOSE_SYSTEM_DIALOGS" .Dans les documents Google:

Action de diffusion: cette action est diffusée lorsqu'une action de l'utilisateur doit demander qu'une boîte de dialogue système temporaire soit rejetée. Quelques exemples de boîtes de dialogue système temporaires sont les suivantes: notification window-shade et les tâches récentes .

Code de travail:

IntentFilter intentFilterACSD = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                    //do what you want here
            }
        }
    };
    this.registerReceiver(broadcastReceiver, intentFilterACSD);
2
Mihuilk

essaye celui-là:

public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    Log.d("Focus debug", "Focus changed !");

    if (!hasFocus) {
        Log.d("Focus debug", "Lost focus !");

    }
}
0
androidBoomer

Est-ce seulement le problème avec ce jeu spécifique? Ou est-ce à chaque jeu que vous jouez?

À côté des onPause() et onResume(), il existe un autre cycle appelé onStop(). Peut-être y a-t-il des choses fondamentales qui se font ici. En appuyant sur ce bouton "windows-open", le jeu ne passera probablement pas à l'état onStop-, alors qu'il sera appuyé sur le bouton "home".

0
DroidBender

J'ai écrit une application qui montre sans ambiguïté le comportement de la clé recent-apps/recents en ce qui concerne les activités et les fragments.

(Toute assertion que des événements de cycle de vie normaux ne sont pas déclenchés par cette clé est manifestement fausse.)

Dans onCreate(), le Activity principal initialise un tableau pour la journalisation de tous les événements de cycle de vie Activity connus et déclenche également le fragment principal à côté de lui dans un second FrameLayout.

Dans onAttach(), le Fragment principal initialise un tableau séparé pour la journalisation de tous les événements de cycle de vie Fragment connus.

À des fins de journalisation, Activité et Fragment traitent onWindowFocusChanged() comme un autre événement du cycle de vie.

Les événements consignés étant horodatés, une indication de "pause" de l'utilisateur peut être donnée lors du rendu (et le rendu a lieu dans onWindowFocusChanged() quand hasFocus==true).

Voici ce que l'utilisateur voit au démarrage de l'application de test:

 enter image description here

Après quelques secondes, l'utilisateur appuie sur recent-apps, attend quelques secondes, puis appuie à nouveau pour voir la vérité:

 enter image description here

NB: Si, au lieu d'utiliser le bouton recent-apps, l'expérience est répétée en: (a) appuyant sur le bouton marche/arrêt de la tablette (b) en appuyant sur le bouton Démarrer 2e activité (c), etc., les résultats sont identiques.

Réponse à l'OP:
Apparemment, il n'y a pas de code capable de détecter le fait d'appuyer sur la touche des applications récentes!

Mais cela n'a pas d'importance, car l'application doit quand même gérer correctement les événements de cycle de vie associés.

0
Bad Loser