Wie überprüfe ich, ob eine Aktivität die letzte im Aktivitätsstapel für eine Anwendung ist?

Antworten:

116

UPDATE (Juli 2015):

Da getRunningTasks () veraltet erhalten, von API 21 ist es besser , folgen raukodraug Antwort oder Ed Burnette einen (I zweite würde es vorziehen).


Es besteht die Möglichkeit, aktuelle Aufgaben und deren Stapel mit ActivityManager zu überprüfen .

Um festzustellen, ob eine Aktivität die letzte ist:

  • Fordern Sie im Manifest android.permission.GET_TASKS-Berechtigungen an.
  • Verwenden Sie den folgenden Code:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

Bitte beachten Sie, dass der obige Code nur gültig ist, wenn Sie eine einzelne Aufgabe haben. Wenn die Möglichkeit besteht, dass für Ihre Anwendung eine Reihe von Aufgaben vorhanden sind, müssen Sie andere taskList- Elemente überprüfen . Lesen Sie mehr über Aufgaben Aufgaben und Back Stack


Sandstar
quelle
25
H9kDroid hat einen korrekten Vorschlag gemacht. Die ausgewählte Antwort ist ein Hack. Man sollte es mit der isTaskRoot()Methode richtig machen .
Sufian
@ Sufian wo ist es Hack besonders? Der Code ist logisch und verwendet offene Android-APIs in der Art und Weise, wie sie verwendet werden sollen (z. B. sollte getRunningTasks verwendet werden, um laufende Aufgaben abzurufen, und man möchte ihn möglicherweise nur zum Zweck der Analyse dieser Aufgaben aufrufen). Die Verwendung von get (0) ist gut dokumentiert und logisch. "Geben Sie eine Liste der Aufgaben zurück, die derzeit ausgeführt werden, wobei die letzten die ersten und die älteren nacheinander sind".
Sandstar
2
getRunningTasks () ist in API Level 21 veraltet.
Gilchris
Kann ich dasselbe für Fragmente tun? Wenn ja, wie dann? Bitte helfen Sie
Sagar Devanga
1
@ Mr.Drew sehen die am höchsten bewertete Antwort von @ raukodraug
David Wasser
167

Ich werde den Kommentar von @ H9kDroid als beste Antwort hier für Leute veröffentlichen, die eine ähnliche Frage haben.

Mit isTaskRoot () können Sie feststellen , ob die Aktivität die Wurzel einer Aufgabe ist.

ich hoffe das hilft

Raukodraug
quelle
1
Können Sie bitte die einzelne Codezeile angeben, damit klar ist, wie isTaskRoot verwendet wird? Vielen Dank.
Kaveesh Kanwal
18
@ TheHunterif (isTaskRoot()) { // do something }
Howettl
3
Das einzige Problem ist, dass bei <= 4.4 ein anderes Verhalten als bei> = 5.x auftritt. Es scheint immer falsch zurückzugeben.
Chubbsondubs
Ich denke, Sie sollten in Betracht ziehen, den in den Kommentaren enthaltenen Beispielcode in die Antwort aufzunehmen, um es zukünftigen Lesern zu erleichtern.
Isac
ausgezeichnete Antwort. in meinem Fall , nachdem der Benutzer klickt auf eine Meldung könnte die Aktivität der Wurzel sein , wenn sie die Anwendung vor geschlossen
dave o grady
19

Hoffe, dies wird neuen Anfängern helfen. Basierend auf den obigen Antworten, die für mich gut funktionieren, teile ich auch Code-Snippets, damit es einfach zu implementieren ist.

Lösung: Ich habe verwendet, isTaskRoot()die true zurückgeben, wenn die aktuelle Aktivität nur eine Aktivität in Ihrem Stapel ist, und außer ich behandle auch den Fall, dass, wenn ich eine Aktivität im Stapel habe, zur letzten Aktivität im Stapel gehe, anstatt eine neue benutzerdefinierte zu öffnen .

In Ihrer Tätigkeit

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }
Abhishek Garg
quelle
16

Es gibt eine einfachste Lösung dafür. Sie können isTaskRoot () in Ihrer Aktivität verwenden

Laxmikant Revdikar
quelle
5

Es gibt zwar einen Weg, dies zu erreichen (siehe andere Antworten), aber ich würde vorschlagen, dass Sie das nicht tun sollten. Normale Android-Anwendungen sollten nicht wissen müssen, ob der Startbildschirm angezeigt wird oder nicht.

Wenn Sie versuchen, Daten zu speichern, fügen Sie den Datenspeichercode in Ihre onPause () -Methode ein. Wenn Sie versuchen, dem Benutzer eine Möglichkeit zu geben, seine Meinung über das Vorhandensein der Anwendung zu ändern, können Sie den Schlüssel für die Zurück-Taste und die onBackPressed () -Methode nach oben / unten abfangen und ihm ein "Sind Sie sicher?" prompt.

Ed Burnette
quelle
1
Wie wäre es, wenn ich einen Dienst benötige, der ausgeführt wird, solange der Benutzer die Aktivität nicht verlassen hat? Ich kann keine der Funktionen wie onStop abfangen, da diese nach dem Ausschalten des Bildschirms aufgerufen werden könnten.
Michael
2
Wenn ein Hintergrunddienst eine Aktivität startet, möchten Sie möglicherweise wissen, ob dies die einzige Aktivität auf dem Stapel ist oder nicht.
Matt W
4

Eine Möglichkeit, dies zu verfolgen, besteht darin, beim Starten einer neuen Aktivität einen Marker einzuschließen und zu überprüfen, ob der Marker vorhanden ist.

Wenn Sie eine neue Aktivität starten, fügen Sie den Marker ein:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

Und Sie können dann so prüfen:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
H9kDroid
quelle
1
Funktioniert nicht, wenn die Aktivität beendet und der Aktivitätsstapel rekonstruiert wird - jede Aktivität nach Bedarf.
AlikElzin-Kilaka
3

Das Problem bei der Verwendung der Lösung von sandrstar ActivityManagerlautet: Sie benötigen eine Berechtigung, um die Aufgaben auf diese Weise abzurufen . Ich habe einen besseren Weg gefunden:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Der Activityuntere Stapel sollte diese Kategorie standardmäßig erhalten, während andere Aktivitäten sie nicht erhalten sollten.
Aber selbst wenn dies auf einigen Geräten fehlschlägt, können Sie es einstellen, während Sie Folgendes starten Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
A. Binzxxxxxx
quelle
Was ist, wenn die Aktivität über eine Push-Benachrichtigung geöffnet wird? Sie haben nicht den CATEGORY LAUNCHER
nbtk
Ich bin mir ziemlich sicher, dass der zweite Teil meiner Antwort noch gilt. Sie können die Kategorie als Hinweis in der Absicht festlegen. In diesem Fall möglicherweise in der Absicht Ihres Benachrichtigungskontexts. Ansonsten können Sie auch Flags verwenden. Siehe diesen Link für eine Benachrichtigungserstellung mit Absicht: stackoverflow.com/questions/13716723/…
A. Binzxxxxxx
Wenn Ihre älteste Aktivität MainActivity ist und jetzt wieder aufgenommen wird und Sie dann eine Push-Benachrichtigung erhalten und den anstehenden Inhalt so einstellen, dass er mit CATEGORY_LAUNCHER geöffnet wird, haben Sie 2 Aktivitäten mit dieser Kategorie. Wahrscheinlich auf verschiedenen Aufgaben
nbtk
Ich bin mir nicht ganz sicher, wie es mit Benachrichtigungen funktioniert. Ich habe sie nie so benutzt wie du hier. Ich bin mir ziemlich sicher, dass es mit diesem Ansatz eine einfache Möglichkeit gibt, aber ich habe seit dem ersten Quartal 2014 keinen Android-Code mehr berührt. Vielleicht möchten Sie für diesen Fall eine zweite Kategorie verwenden? Oder eine Flagge? Aber ich denke, es ist wichtig, so zu arbeiten. Wie wäre es, wenn Sie die Hauptaktivität starten und eine Art Metainformation hinzufügen, um dann die richtige Aktivität zu öffnen?
A. Binzxxxxxx
2

Ich habe für alle meine Aktivitäten eine Basisklasse erstellt, die AppCompatActivity erweitert und über einen statischen Zähler verfügt:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

Dies hat bisher gut genug funktioniert; und unabhängig von der API-Version. Es erfordert natürlich, dass alle Aktivitäten diese Basisklasse erweitern - was sie in meinem Fall tun.

Bearbeiten: Ich habe eine Instanz bemerkt, bei der der Zähler auf Null sinkt, bevor die App vollständig beendet wird. In diesem Fall wird die Ausrichtung geändert und nur eine Aktivität ist geöffnet. Wenn sich die Ausrichtung ändert, wird die Aktivität geschlossen und eine andere erstellt. Dies onDestroyedwird für die letzte Aktivität onCreateaufgerufen und wird dann aufgerufen, wenn dieselbe Aktivität mit der geänderten Ausrichtung erstellt wird. Dieses Verhalten muss berücksichtigt werden. OrientationEventListener könnte möglicherweise verwendet werden.

Per Löwgren
quelle
0

Android Geräte ein Activity - Stack, ich schlage vor , Sie darüber zu lesen hier . Es sieht so aus, als ob Sie nur die aufrufende Aktivität abrufen möchten : getCallingActivity(). Wenn die aktuelle Aktivität die erste Aktivität in Ihrer Anwendung ist und die Anwendung über den Startbildschirm gestartet wurde, sollte sie (ich nehme an) zurückkehren null.

Gyan alias Gary Buyn
quelle
9
Dies funktioniert nicht, da getCallingActivity () null zurückgibt, wenn die Aktivität nicht über startActivityForResult () gestartet wurde.
H9kDroid
0

Das einzige, was hier übersehen wurde, ist der Klick auf die "Home-Taste". Wenn diese Option aktiviert ist, können Sie dies nicht an Ihrer Aktivität erkennen. Daher ist es besser, den Aktivitätsstapel programmgesteuert zu steuern, indem Sie die Taste "Zurück" drücken und zur gewünschten Aktivität wechseln oder nur die notwendigen Schritte machen.

Darüber hinaus können Sie nicht sicher sein, ob das Starten Ihrer Aktivität aus der Liste "Letzte Aktivität" erkannt werden kann, indem einige zusätzliche Daten in die Absicht zum Öffnen der Aktivität voreingestellt werden, da diese in diesem Fall wiederverwendet werden.

ACM64
quelle