Zakończ wszystkie poprzednie działania


368

Moja aplikacja ma następujące ekrany przepływu:

Home->screen 1->screen 2->screen 3->screen 4->screen 5

Teraz mam wspólny log out przycisk na każdym ekranie

( Home/ screen 1 / screen 2 /screen 3/ screen 4 / screen 5)

Chcę, aby po kliknięciu przycisku wylogowania (z dowolnego ekranu) wszystkie ekrany zostały zakończone i Log inotworzył się nowy ekran .

Próbowałem prawie wszystkich, FLAG_ACTIVITYaby to osiągnąć. Przeglądam także niektóre odpowiedzi w przepełnieniu stosu, ale nie jestem w stanie rozwiązać problemu. Moja aplikacja działa na Androidzie 1.6, więc nie mogę jej używaćFLAG_ACTIVITY_CLEAR_TASK

Czy jest jakiś sposób na rozwiązanie tego problemu?


Czy prowadzisz zagnieżdżone działania za pomocą startActivityForResult?
woodshy 13.06.11

nie. Wszystkie działania rozpoczynają się od startActivity.
Tanmay Mandal

Korzystam z zagnieżdżonych działań, podczas gdy dorsz uruchamia metodę finishaffinitytask () w zagnieżdżonych działaniach. czy to zmienia zachowanie? ponieważ czasami otrzymuję komunikat o niepowodzeniu dostarczania wyniku ResultInfo, gdy uruchomione jest poleceniekończenie zadania.
Ripal Tamboli

Sprawdź tę odpowiedź, to z pewnością pomoże ci stackoverflow.com/a/25159180/2732632
Kimmi Dhingra

3
Android 21 wprowadził Activity.finishAndRemoveTask ().
Joseph Johnson

Odpowiedzi:


543

Posługiwać się:

Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Spowoduje to wyczyszczenie wszystkich działań w domu.

Zakładając, że kończysz ekran logowania, gdy użytkownik loguje się i tworzona jest strona główna, a następnie wszystkie ekrany od 1 do 5 na górze tego. Kod, który opublikowałem, spowoduje powrót do ekranu głównego po zakończeniu wszystkich innych działań. Możesz dodać dodatkowy cel i przeczytać to w aktywności na ekranie głównym i zakończyć również (może ponownie uruchomić ekran logowania z tego miejsca lub coś takiego).

Nie jestem pewien, ale możesz także spróbować zalogować się przy użyciu tej flagi. W tym przypadku nie wiem, jak zostaną uporządkowane działania. Więc nie wiem, czy to wyczyści te pod ekranem, na którym jesteś, w tym ten, na którym aktualnie jesteś, ale zdecydowanie jest to dobra droga.

Mam nadzieję że to pomoże.


Użytkownik pokazuje swój pierwszy ekran jako ekran główny, to jest główny problem.
Tanmay Mandal

Cóż, mam swoją odpowiedź, musisz wrócić do ekranu głównego i dokończyć ten. więc proces wywołuje powyższe zamiary z dowolnego ekranu. otrzymaj zamiar na ekranie głównym i od razu pomyśl o logowaniu i ukończ dom po metodzie startActivity. możesz także przesłonić oczekującą animację, ustawiając na zero dla wejść i wyjść, aby nie pokazywała przejścia (robię to, ponieważ wydaje się to trochę szybsze). więc to powinno działać dobrze dla tego, czego potrzebujesz.
DArkO

10
Zamiast zadeklarować działanie jako singleInstance, rozważ użycie FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOPjako flagi dla zamiaru. To zakończy działania interwencyjne i rozpocznie (lub przywróci na pierwszy plan) pożądane działanie.
CommonsWare

13
@ CommonsWare Dodanie intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);do mojej aktywności nie pomogło mi. Nie zakończyło interwencji. Po ponownym naciśnięciu ekranu logowania widzę poprzednie działania. Oto mój kod Intent intent=new Intent(BaseActivity.this, Login.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);startActivity(intent);.
Tanmay Mandal,

26
ten kod usuwa tylko górny stos działań, aby wyczyścić wszystkie działania intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
Ajay Venugopal

318

Możesz spróbować Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK. Całkowicie wyczyści wszystkie poprzednie działania i rozpocznie nowe działanie.


11
Właściwe rozwiązanie, ale tylko API 11+
riwnodennyk

Skończyło się na użyciu tej dodatkowej flagi, ponieważ nie powoduje to opóźnienia przy wyświetlaniu głównej aktywności (nie zrestartuje jej, więc jest znacznie szybsza).
Maurizio

2
@riwnodennyk dlaczego API 11+?
Muhammad Babar

17
Użyj IntentCompat.FLAG_ACTIVITY_CLEAR_TASK dla wersji wcześniejszych 11
Steven Pena

2
@ono Tak. To powinno być wszystko, czego potrzebujesz. Upewnij się, że tryb uruchamiania działania docelowego jest ustawiony w manifeście jako „singleTask”.
Steven Pena,

137

Przed uruchomieniem nowego działania wystarczy dodać następujący kod:

finishAffinity();

Lub jeśli chcesz, aby działał w poprzednich wersjach Androida:

ActivityCompat.finishAffinity(this);

12
ActivityCompat.finishAffinity (this); wywołuje activity.finish () dla api <16. Więc to nie zadziała.
Aamir Abro,

1
@Beto Caldas, sam potwierdziłem kod źródłowy, nie będzie działać dla API <16, jak wspomniał AamirAbro. To po prostu zakończy działanie, które przekazujesz API <16.
HendraWD

39

Gdy użytkownik chce wyjść ze wszystkich otwartych działań , powinien nacisnąć przycisk, który ładuje pierwsze działanie, które jest uruchamiane po uruchomieniu aplikacji, wyczyścić wszystkie pozostałe działania, a następnie zakończyć ostatnie działanie. Uruchom następujący kod, gdy użytkownik naciśnie przycisk wyjścia. W moim przypadku LoginActivityjest to pierwsze działanie w moim programie do uruchomienia.

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

Powyższy kod usuwa wszystkie działania oprócz LoginActivity. Następnie wstaw następujący kod do LoginActivity's' onCreate(...), aby nasłuchiwać, kiedy LoginActivityzostanie odtworzony i przekazany został sygnał „EXIT”:

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();  
}

Dlaczego tak trudny jest przycisk wyjścia w Androidzie?

System Android stara się zniechęcić użytkownika do posiadania przycisku „wyjdź” w aplikacji, ponieważ chce, aby użytkownik nigdy nie dbał o to, czy używane przez niego programy działają w tle, czy nie.

Programiści systemu operacyjnego Android chcą, aby Twój program mógł przetrwać nieoczekiwane zamknięcie i wyłączenie telefonu, a gdy użytkownik uruchomi ponownie program, rozpocznie pracę od miejsca, w którym zakończył. Dzięki temu użytkownik może odbierać połączenia telefoniczne podczas korzystania z aplikacji i otwierać mapy, które wymagają zwolnienia aplikacji w celu uzyskania większej ilości zasobów.

Gdy użytkownik wznawia twoją aplikację, odbiera ją tam, gdzie ją przerwał, bez żadnych zakłóceń. Ten przycisk wyjścia przejmuje władzę od menedżera aktywności, potencjalnie powodując problemy z automatycznie zarządzanym cyklem życia programu Android.


31
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Działa to dla wszystkich wersji Androida. Gdzie IntentCompatklasa dodana w bibliotece wsparcia Android.


IntentCompat.FLAG_ACTIVITY_CLEAR_TASKnie jest rozpoznawany, użyj Intentzamiast IntentCompat.
CoolMind,

30

Użyj następujących działań

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

usuń flagę CLEAR_TASK w celu użycia fragmentu.

Mam nadzieję, że może to być przydatne dla niektórych osób.


24

Chyba się spóźniłem, ale odpowiedź jest prosta i krótka. W działaniu znajduje się metoda finishAffinity (), która zakończy bieżącą aktywność i wszystkie działania nadrzędne, ale działa tylko w systemie Android 4.1 lub nowszym.

W przypadku API 16+ użyj

finishAffinity();

Dla osób poniżej 16, użyj

ActivityCompat.finishAffinity(YourActivity.this);

Mam nadzieję, że to pomoże!


21

Od developer.android.com :

public void finishAffinity ()

Dodano w API 16 poziom

Zakończ to działanie, a także wszystkie działania bezpośrednio pod nim w bieżącym zadaniu, które mają to samo powinowactwo. Jest to zwykle używane, gdy aplikacja może zostać uruchomiona do innego zadania (na przykład z ACTION_VIEW typu treści, który rozumie), a użytkownik skorzystał z nawigacji w górę, aby przełączyć się z bieżącego zadania do własnego. W takim przypadku, jeśli użytkownik przejdzie w dół do innych działań drugiej aplikacji, wszystkie z nich powinny zostać usunięte z pierwotnego zadania jako część przełącznika zadań.

Pamiętaj, że to wykończenie nie pozwala na dostarczenie wyników do poprzedniej aktywności, a wyjątek zostanie zgłoszony, jeśli spróbujesz to zrobić.


19

Na marginesie, dobrze wiedzieć
Ta odpowiedź działa ( https://stackoverflow.com/a/13468685/7034327 )

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
this.finish();

podczas gdy to nie działa

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

.setFlags() zastępuje wszystkie poprzednie flagi i nie dodaje żadnych nowych flag, gdy to .addFlags()robi.

To też zadziała

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Świetne wyjaśnienie różnicy między setFlag a addFlag, dziękuję
Pelanes

13

Jeśli twoja aplikacja ma minimalną wersję SDK 16, możesz użyć finishAffinity ()

Zakończ to działanie, a także wszystkie działania bezpośrednio pod nim w bieżącym zadaniu, które mają to samo powinowactwo.

Dla mnie to działa. Na ekranie Top Payment usuń wszystkie aktywacje back-stack,

@Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29


10

Rozwiązanie, które wdrożyłem w tym celu (myślę, że znalazłem je gdzieś na Stack Overflow, ale nie pamiętam, więc dzięki temu, kto to zrobił):

Z dowolnego ze swoich działań wykonaj to:

// Clear your session, remove preferences, etc.
Intent intent  = new Intent(getBaseContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Następnie w swojej LoginActivity, nadpisz onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

3
To zazwyczaj bardzo zły pomysł, ponieważ może działać, wprowadza punkt kontaktowy, który może się złamać w przyszłości i trudno będzie go debugować. Mówię ci z doświadczenia :)
Martin Marconcini

10

W przypadku przycisku wylogowania na ostatnim ekranie aplikacji użyj tego kodu w detektorze przycisku wylogowania, aby zakończyć wszystkie otwarte poprzednie działania, a problem zostanie rozwiązany.

{
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}

8
    Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

6
dlaczego FLAG_ACTIVITY_CLEAR_TASK dwa razy?
Choletski

1
Z tego, co rozumiem, .setFlags zastępuje poprzednie flagi i nie dołącza żadnych flag. .addFlags jest tym, czego chciałeś użyć, jak sądzę? Przyczyna całego kodu powyżej i1.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); zostaje
usunięty

addFlags Działa dla mnie
Jamil,

1
setFlagszastąpi wszystkie poprzednie, więc ostatnie setFlagsjest tylko ważne, poprzednie są zastąpione. Więc nie musisz dzwonići1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mtrakal

8

Mam ten sam problem, z którego możesz skorzystać IntentCompat, taki jak ten:

import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);

ten kod działa dla mnie.

Interfejs API Androida 17


8

W moim przypadku używam finishAffinity()funkcji w ostatniej aktywności, takiej jak:

finishAffinity()
startHomeActivity()

Mam nadzieję, że się przyda.



6

Zaloguj się> Strona główna-> ekran 1-> ekran 2-> ekran 3-> ekran 4-> ekran 5

na ekranie 4 (lub dowolnym innym) ->

StartActivity (Zaloguj się)
z
FLAG_ACTIVITY_CLEAR_TOP


2
Po naciśnięciu przycisku Wstecz wszystkie poprzednie działania są wyświetlane w kolejności, w jakiej były. Działania te należy zamknąć, gdy kliknięty zostanie przycisk wylogowania, na stosie będzie tylko jedno działanie i będzie to działanie związane z logowaniem. ekran logowania. Użytkownik uruchamia się z ekranu głównego.
Tanmay Mandal

6

dla API> = 15 do API 23 proste rozwiązanie.

 Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
 nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
 startActivity(nextScreen);
 ActivityCompat.finishAffinity(currentActivity.this);

Opracuj swoją odpowiedź, aby każdy mógł z niej skorzystać.
Shubhamoy,

5

Jeśli korzystasz startActivityForResult()z poprzednich działań, po prostu zastąp OnActivityResult()i wywołaj finish();metodę znajdującą się w nim we wszystkich działaniach. Spowoduje to wykonanie zadania ...


Nie, używam startActivitytylko.
Tanmay Mandal

Trudno będzie utrzymać onActivityResultkażdą aktywność. Wdrożyłem sugestię DArkO i osiągnąłem swój cel i dziękuję za pomoc.
Tanmay Mandal

3

Gdy użytkownik kliknie przycisk wylogowania, a następnie napisze następujący kod:

Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

A także, gdy po zalogowaniu, jeśli wywołasz nową aktywność, nie używaj kończenia ();


2

Po prostu, kiedy przejdziesz z ekranu logowania, a nie po zakończeniu ekranu logowania.

Następnie we wszystkich działaniach do przodu użyj tego do wylogowania:

final Intent intent = new Intent(getBaseContext(), LoginScreen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

Działa idealnie.


1

Jeśli zalogujesz użytkownika, screen 1a następnie przejdziesz do innych ekranów, użyj

Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Po naciśnięciu przycisku Wstecz wszystkie poprzednie działania są wyświetlane w kolejności, w jakiej były. Działania te należy zamknąć, gdy kliknięty zostanie przycisk wylogowania, na stosie będzie tylko jedno działanie i będzie to działanie związane z logowaniem.
Tanmay Mandal

Jeśli chcesz tego zachowania, musisz zastąpić onKeyDowni onBackPressed(lub onKeyDown, jeśli chcesz obsługiwać wersje Androida <2.0) w każdym ze swoich działań (oprócz logowania) i startActivity(login)tam, jak pokazano powyżej.
Gabriel Negut,

Mam przycisk, który przeniesie mnie do ekranu logowania kończącego wszystkie działania na stosie. Czy to możliwe?
Tanmay Mandal

1

Znalazłem w ten sposób, wyczyści całą historię i wyjdzie

Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
Intent intent = new Intent(getApplicationContext(), SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

finish();
System.exit(0);

1

Chyba się spóźniłem, ale odpowiedź jest prosta i krótka. W działaniu znajduje się metoda finishAffinity (), która zakończy bieżącą aktywność i wszystkie działania nadrzędne, ale działa tylko w systemie Android 4.1 lub nowszym.

W przypadku API 16+ użyj

finishAffinity ();

Dla osób poniżej 16, użyj

ActivityCompat.finishAffinity (YourActivity.this);

Mam nadzieję, że to pomoże!

shareedit odpowiedział 27 maja 18 o 8:03

Akshay Taru


0

Uważam, że to rozwiązanie działa na każdym urządzeniu pomimo poziomu interfejsu API (nawet <11)

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

0

Najlepszy sposób na zamknięcie wszystkich poprzednich działań i wyczyszczenie pamięci

finishAffinity()
System.exit(0);

0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
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.