Jak sprawdzić, czy aktywność jest ostatnią w stosie aktywności dla aplikacji?


Odpowiedzi:


116

AKTUALIZACJA (lipiec 2015):

Od getRunningTasks () się przestarzałe, z API 21 lepiej podążać raukodraug odpowiedź lub Ed Burnette jeden (wolałbym drugi).


Istnieje możliwość sprawdzenia aktualnych zadań i ich stosu za pomocą ActivityManagera .

Aby więc ustalić, czy czynność jest ostatnią:

  • zażądaj uprawnień android.permission.GET_TASKS w manifeście.
  • Użyj poniższego kodu:

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

Pamiętaj, że powyższy kod będzie ważny tylko wtedy, gdy masz jedno zadanie. Jeśli istnieje taka możliwość, że dla Twojej aplikacji będzie istniała taka liczba zadań - musisz sprawdzić inne elementy taskList . Przeczytaj więcej o zadaniach Zadania i stosie wstecznym



25
H9kDroid podał poprawną sugestię. Wybrana odpowiedź to hack. Należy to zrobić we właściwy sposób isTaskRoot()metodą.
Sufian

@Sufian, gdzie szczególnie się włamuje? Kod jest logiczny i wykorzystuje otwarte Android API w sposób, w jaki zamierzał być używany (np. GetRunningTasks powinno być używane do uruchamiania zadań i można chcieć wywołać go tylko w celu analizy tych zadań). Użycie metody get (0) jest dobrze udokumentowane i logiczne: „Zwróć listę zadań, które są aktualnie uruchomione, przy czym najnowsze to pierwsze i starsze w kolejności”.
sandrstar

2
Funkcja getRunningTasks () jest przestarzała na poziomie API 21.
gilchris,

Czy mogę zrobić to samo dla fragmentów. Jeśli tak, to w jaki sposób? Proszę o pomoc
Sagar Devanga

1
@ Mr.Drew zobacz najwyższą głosowaną odpowiedź od @ raukodraug
David Wasser

167

Zamierzam zamieścić komentarz @ H9kDroid jako najlepszą odpowiedź dla osób, które mają podobne pytanie.

Możesz użyć isTaskRoot (), aby dowiedzieć się, czy działanie jest katalogiem głównym zadania.

mam nadzieję, że to pomoże


1
czy możesz podać jedną linię kodu, aby jasno określić, jak używać isTaskRoot. Dzięki.
Kaveesh Kanwal

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
Jedynym problemem jest to, że w <= 4.4 widzę, że zachowuje się inaczej niż w> = 5.x. Wydaje się, że zawsze zwraca fałsz.
chubbsondubs

Myślę, że powinieneś rozważyć włączenie do odpowiedzi przykładowego kodu podanego w komentarzach, aby ułatwić przyszłym czytelnikom.
Isac

doskonała odpowiedź. w moim przypadku po kliknięciu przez użytkownika powiadomienia aktywność może być korzeniem, jeśli wcześniej zamknął aplikację
dave o grady

19

Mam nadzieję, że pomoże to nowym początkującym, Opierając się na powyższych odpowiedziach, które dla mnie działają dobrze, udostępniam również fragment kodu, więc będzie łatwy do wdrożenia.

rozwiązanie: użyłem, isTaskRoot()które zwracają wartość true, jeśli bieżąca aktywność jest tylko aktywnością na twoim stosie, a inna niż ja również obsługuję przypadek, w którym jeśli mam jakąś aktywność na stosie, przejdź do ostatniej aktywności na stosie zamiast otwierania nowej niestandardowej.

W Twojej działalności

   @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();
        }

    }


5

Chociaż może istnieć sposób, aby to osiągnąć (zobacz inne odpowiedzi), sugeruję, aby tego nie robić. Zwykłe aplikacje na Androida nie powinny wiedzieć, czy ekran główny ma się wyświetlić, czy nie.

Jeśli próbujesz zapisać dane, umieść kod zapisujący dane w metodzie onPause (). Jeśli próbujesz dać użytkownikowi możliwość zmiany zdania na temat istniejącej aplikacji, możesz przechwycić klawisz w górę / w dół dla klawisza Wstecz i metody onBackPressed () i przedstawić im pytanie „Czy na pewno?” skłonić.


1
Co powiesz na to, że potrzebuję usługi działającej tak długo, jak użytkownik nie opuścił aktywności? Nie mogę przechwycić żadnej z funkcji, takich jak onStop, ponieważ można je wywołać po wyłączeniu ekranu.
Michael

2
Jeśli usługa w tle uruchamia działanie, być może chcesz wiedzieć, czy jest to jedyne działanie na stosie.
Matt W

4

Jednym ze sposobów śledzenia tego jest dołączenie znacznika podczas rozpoczynania nowej czynności i sprawdzenie, czy znacznik istnieje.

Za każdym razem, gdy zaczynasz nową aktywność, wstaw znacznik:

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

Możesz to sprawdzić w ten sposób:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
Nie działa, jeśli działanie zostanie zabite, a stos działań zostanie odtworzony - każde działanie na żądanie.
AlikElzin-kilaka

3

Problem z użyciem rozwiązania sandrstar ActivityManagerjest następujący: potrzebujesz pozwolenia na pobieranie zadań w ten sposób. Znalazłem lepszy sposób:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Pozycja Activityna dole stosu powinna zawsze mieć domyślnie tę kategorię, podczas gdy inne działania jej nie powinny.
Ale nawet jeśli to się nie powiedzie na niektórych urządzeniach, możesz to ustawić podczas uruchamiania Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

Co się stanie, jeśli aktywność zostanie otwarta z powiadomienia push? Nie mają KATEGORII LAUNCHER
nbtk

Jestem pewien, że druga część mojej odpowiedzi nadal obowiązuje. Możesz ustawić kategorię jako wskazówkę w zamiarze. W tym przypadku może to być cel twojego powiadomienia. Poza tym możesz również użyć do tego flag. zobacz ten link do tworzenia powiadomienia z zamiarem: stackoverflow.com/questions/13716723/ ...
A. Binzxxxxxx

Mimo to, jeśli Twoją najstarszą aktywnością jest MainActivity, a teraz została ona wznowiona, a następnie otrzymasz powiadomienie push i ustawisz pendingIntent na otwieranie w CATEGORY_LAUNCHER, będziesz mieć 2 działania z tą kategorią. Prawdopodobnie jednak przy innych zadaniach
nbtk

Nie jestem do końca pewien, jak to działa z powiadomieniami. Nigdy ich nie używałem tak, jak ty to robisz tutaj. Jestem całkiem pewien, że przy takim podejściu można to łatwo zrobić, ale nie dotykałem kodu Androida od I kwartału 2014 r. Może chcesz użyć w tym przypadku drugiej kategorii? Albo jakaś flaga? Ale myślę, że to tak działa. A co powiesz na rozpoczęcie głównego działania i dodanie jakichś metainformacji, aby otworzyć prawidłowe działanie?
A. Binzxxxxxx,

2

Stworzyłem klasę bazową dla wszystkich moich działań, rozszerzając AppCompatActivity i która ma statyczny licznik:

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

Jak dotąd działało to wystarczająco dobrze; i niezależnie od wersji API. Wymaga to oczywiście, aby wszystkie działania rozszerzały tę klasę bazową - co w moim przypadku robią.

Edycja: Zauważyłem jeden przypadek, gdy licznik spada do zera, zanim aplikacja całkowicie się zamknie, czyli wtedy, gdy orientacja zostanie zmieniona i tylko jedno działanie jest otwarte. Kiedy zmienia się orientacja, działanie jest zamykane i tworzone jest inne, tak więc onDestroyedwywoływane jest ostatnie działanie, a następnie onCreatewywoływane, gdy to samo działanie jest tworzone ze zmienioną orientacją. Należy uwzględnić to zachowanie; Ewentualnie można użyć OrientationEventListener .


0

Android implementuje stos aktywności, sugeruję, abyś przeczytał o tym tutaj . Wygląda na to wszystko, co chcesz zrobić jest jednak odzyskać aktywność numerem: getCallingActivity(). Jeśli bieżąca aktywność jest pierwszą aktywnością w Twojej aplikacji, a aplikacja została uruchomiona z ekranu głównego, powinna (zakładam) powrócić null.


9
To nie zadziała, ponieważ getCallingActivity () zwróci wartość null, jeśli działanie nie zostało uruchomione przez startActivityForResult ().
H9kDroid

0

Jedyną rzeczą, której tutaj brakowało, jest kliknięcie „klawisza Home”, po aktywacji nie można tego wykryć w swojej aktywności, więc lepiej byłoby programowo kontrolować stos aktywności, obsługując naciśnięcie klawisza „Wstecz” i przechodząc do żądanej czynności lub po prostu wykonując niezbędne kroki.

Ponadto nie możesz być pewien, że rozpoczęcie aktywności z listy „Ostatnia aktywność” można wykryć, ustawiając dodatkowe dane w celu otwarcia czynności, ponieważ w takim przypadku są one ponownie wykorzystywane.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.