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?

Tanmay Mandal
źródło
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.

DArkO
źródło
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.

Kong Ken
źródło
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);
Henrique
źródło
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.

Eric Leschinski
źródło
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.

Klejnot
źródło
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.

Aristo Michael
źródło
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!

Akshay Taru
źródło
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ć.

gmrl
źródło
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);
Jan
źródło
Ś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

Jaydeep purohit
źródło
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);
}
Andy
źródło
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);
}
Amrit
źródło
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();
Prashant Kumar
źródło
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

Adnan Abdollah Zaki
źródło
8

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

finishAffinity()
startHomeActivity()

Mam nadzieję, że się przyda.

Djek-Grif
źródło
7

zamiast używać finish()wystarczy użyćfinishAffinity();

Hitesh Kushwah
źródło
1
Dobra odpowiedź, ale wymaga API 16
Akshay Taru
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

Plamen Nikołow
źródło
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);
Kamal Bunkar
źródło
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 ...

ngesh
źródło
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 ();

nikki
źródło
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.

Asad Rao
źródło
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);
Gabriel Negut
źródło
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);
pirooz jenabi
źródło
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

Samuel Quiroz
źródło
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);
priyankvex
źródło
0

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

finishAffinity()
System.exit(0);
Shivam Tripathi
źródło
0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
Kishan Solanki
źródło