webentwicklung-frage-antwort-db.com.de

Erkennen von Klicks auf die Systemschaltflächen "Recent Apps" (Honeycomb +)

Ich frage mich, welche Methode diese Schaltfläche aufruft.

enter image description here

Mein Spiel wird immer pausiert/fortgesetzt, es sei denn, ich benutze diese Schaltfläche. Diese Schaltfläche ruft anscheinend nicht die Methoden onPause() und onResume() eines Activity auf. Es funktioniert, wenn ich das Spiel beende, zu einem anderen Fenster gehe (wie dem auf dem Bild) und dann diesen Knopf benutze, um fortzufahren. Aber wenn ich diesen Knopf drücke, pausiert das Spiel im Spiel, aber der Thread wird nicht fortgesetzt, wie jedes Mal, das Spiel bleibt einfach auf dem Bildschirm stehen und flackert ein bisschen.

Schwer zu erklären, aber ich hoffe, ich bin ein bisschen klar, wenn nicht, fragen Sie!

24
Green_qaue

Keine der standardmäßigen Activity Lifecycle - Methoden wird aufgerufen, wenn die Schaltfläche "Recent Apps" gedrückt wird. Die Aktivität bleibt nach der Liste der zuletzt geöffneten Apps aktiv. Durch den halbtransparenten linken Teil dieser Liste können Sie sogar beobachten, dass die Anwendungsanimation noch ausgeführt wird, wenn Sie ein Spiel mit einer Animation ausführen, die diese Situation nicht richtig handhabt. Tatsächlich haben viele Spiele in Google Play diese Situation nicht richtig gemeistert, selbst gute wie Angry Birds.

Die einzige Aktivitätsmethode, die aufgerufen wird, wenn der Benutzer die Liste "Zuletzt verwendete Apps" öffnet (oder daraus zurückkehrt), ist onWindowFocusChanged mit dem booleschen Parameter hasFocus. Wenn der Benutzer die Liste der zuletzt verwendeten App-Methoden öffnet, entspricht onWindowFocusChanged(), die mit hasFocus aufgerufen wurde, false, und dieselbe Methode, die mit hasFocus aufgerufen wurde, entspricht true, wenn der Benutzer in dieser Liste auf Zurück drückt.

22
HitOdessit

Um festzustellen, wann die Schaltfläche "Letzte Apps" gedrückt wurde, können Sie den Eingabehilfedienst verwenden. Sie müssen Ihren eigenen Eingabehilfedienst ausführen und Ereignisse mit dem Typ "TYPE_WINDOW_STATE_CHANGED" empfangen und den Klassennamen des Ereignisses überprüfen.

  1. Lesen Sie mehr über Accessibility Service im Android-Entwickler. Richten Sie Ihren eigenen Eingabehilfedienst ein und fragen Sie den Benutzer um Erlaubnis.
  2. Überschreibe in deinem Accessibility Service die Methode onAccessibilityEvent()
  3. Bei dieser Methode erhalten Sie das Objekt AccessibilityEvent event. Dieses Objekt enthält alle erforderlichen Informationen zu einem Ereignis, das gerade auf Ihrem Gerät aufgetreten ist.
  4. Wir interessieren uns für den ClassName. ClassName kann manchmal null sein, vergessen Sie also nicht! = Null check. Die Paketnamen des Fensters "Zuletzt verwendete Apps" variieren je nach Android-Version:

    • 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" (Buchstabe "s" wurde hinzugefügt)

Ich kenne den Klassennamen für ältere Geräte nicht, aber ich glaube nicht, dass sie 2017 von jemandem gewartet werden.

Sie werden also so etwas haben:

@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.
    }
}

Ich habe es auf den folgenden realen Geräten getestet: LG, Nexus, Sony und virtuellen Geräten: Motorola, Samsung.

Wenn jemand eine Ausnahme für diese Klassennamen kennt, schicke mich bitte an.

5
Kirill Karmazin

Ich habe das gleiche Problem, ich habe dieses Problem wie folgt gelöst

Schaltfläche "Registrieren" klicken Sie auf "Broadcast" für "Home" und "RecentApp"

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

Jetzt BroadcastReceiver-Code

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

Aber vergessen Sie nicht, unregisterReceiver BroadcastReceiver

4
Lokesh

Ich hatte ein ähnliches Problem, also musste ich wissen, wann der Benutzer die Taste für die letzten Apps drückt (Menütaste in alten Android-Versionen). Nach einigen Stunden Recherche habe ich kein Ereignis gefunden, das erfasst werden könnte, wenn die Home-Taste oder die Menü-Taste gedrückt wird. Ich fand, dass es eine längere Zeit dauert, um onStop () aufzurufen, wenn der Benutzer die Home-Taste drückt. Daher habe ich einen Trick gefunden, um zwischen diesen Schlepptasten zu unterscheiden, die sich auf die Reaktionszeit beziehen und zwei Methoden überschreiben:

@Override

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

@Override

public void onStop() {
    super.onStop();
    if (isNotPower) {
        defStop = System.currentTimeMillis() - userLeaveTime;
        if (defStop > 200 ) {
            //home button
        }
        if (defStop < 200) {
            //recent apps button
        }
    }
    isNotPower = false;
}
  • der isNotPower-Parameter, der überprüft, ob der Netzschalter nicht gedrückt wurde. Wenn der Netzschalter gedrückt wurde, wird die onStop () -Methode aufgerufen, nicht jedoch die onUserLeaveHint ().
3
khaled_alokby

Die beste Möglichkeit, die ich gefunden habe, besteht darin, die Broadcast-Aktion "ACTION_CLOSE_SYSTEM_DIALOGS" anzuhören. In den Google-Dokumenten:

Broadcast-Aktion: Wird gesendet, wenn eine Benutzeraktion ein temporäres Systemdialogfeld zum Schließen anfordert. Einige Beispiele für temporäre Systemdialogfelder sind das Benachrichtigungsfenster und das Dialogfeld für aktuelle Aufgaben .

Arbeitscode:

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

probier diese:

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

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

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

    }
}
0
androidBoomer

Ist das nur das Problem mit diesem bestimmten Spiel? Oder ist es bei jedem Spiel, das du spielst?

Neben den onPause() und onResume() gibt es einen weiteren Zyklus mit dem Namen onStop(). Vielleicht werden hier einige grundlegende Dinge getan. Wenn Sie diesen "Windows-Open" -Button drücken, wechselt das Spiel wahrscheinlich nicht in den Zustand onStop-, wohingegen Sie den "Home" -Button drücken.

0
DroidBender

Ich habe eine App geschrieben, die das Verhalten der Recent-Apps / Recents Key in Bezug auf Aktivitäten und Fragmente eindeutig demonstriert.

(Jegliche Behauptung, dass normale Lebenszyklusereignisse nicht durch diesen Schlüssel ausgelöst werden, ist offensichtlich falsch.)

In onCreate() initialisiert main Activity ein Array für die Protokollierung aller bekannten Activity Lifecycle-Ereignisse und löst auch das Hauptfragment in einem zweiten FrameLayout neben sich aus.

In onAttach() initialisiert das main Fragment ein separates Array für die Protokollierung aller bekannten Fragment Lifecycle-Ereignisse.

Zu Protokollierungszwecken behandeln Aktivität und FragmentonWindowFocusChanged() nur als ein weiteres Lebenszyklusereignis.

Protokollierte Ereignisse werden mit einem Zeitstempel versehen, sodass beim Rendern eine Benutzerpause angezeigt werden kann (und das Rendern erfolgt in onWindowFocusChanged() when hasFocus==true).

Dies sieht der Benutzer, wenn die Test-App gestartet wird:

 enter image description here

Nach ein paar Sekunden drückt der Benutzer recent-apps , wartet ein paar Sekunden und drückt dann erneut, um die Wahrheit zu sehen:

 enter image description here

NB: Wenn anstelle der Taste für die letzten Apps das Experiment wiederholt wird, indem (a) die Taste zum Ein- und Ausschalten des Tablets gedrückt wird (b) die Taste zum Starten der zweiten Aktivität (c) usw. gedrückt wird, werden identische Ergebnisse erzielt.

Antwort an OP:
Anscheinend gibt es keinen Code, der das tatsächliche Drücken der Taste der letzten Apps erkennen kann!

Dies spielt jedoch keine Rolle, da die App die zugehörigen Lebenszyklusereignisse ohnehin korrekt verarbeiten muss.

0
Bad Loser