Przy wylogowaniu, Wyczyść stos historii aktywności, uniemożliwiając przycisk "Wstecz" otwarcie aktywności tylko dla zalogowanych
Wszystkie działania w mojej aplikacji wymagają zalogowania użytkownika, aby wyświetlić. Użytkownicy mogą wylogować się z prawie każdej aktywności. Jest to wymóg aplikacji. W każdym momencie, jeśli użytkownik wyloguje się, chcę wysłać użytkownika do loginu Activity
. W tym momencie chcę, aby ta aktywność była na dole stosu historii, aby naciśnięcie przycisku "Wstecz" zwróciło użytkownika na ekran główny Androida.
Widziałem to pytanie zadawane w kilku różnych miejscach, wszystkie odpowiedzi były podobne odpowiedzi (które opisuję tutaj), ale chcę je tutaj ułożyć, aby zebrać opinie.
Próbowałem otworzyć aktywność logowania, ustawiając jej flagi Intent
na FLAG_ACTIVITY_CLEAR_TOP
, co wydaje się robić tak, jak opisano w dokumentacji, ale nie osiąga mojego celu umieszczenia aktywności logowania na dole stosu historii i uniemożliwienia użytkownikowi powrotu do wcześniej widzianych aktywności zalogowanych. Próbowałem również użyć android:launchMode="singleTop"
do logowania w manifeście, ale nie osiągnęło to mojego cel albo (i wydaje się, że i tak nie ma efektu).
Uważam, że muszę albo wyczyścić stos historii, albo zakończyć wszystkie wcześniej otwarte działania.
JednÄ… z opcji jest sprawdzenie statusu zalogowanego i finish()
, jeśli nie jest zalogowany. Nie podoba mi się ta opcja, ponieważ przycisk Wstecz będzie nadal dostępny do użycia, nawigując wstecz, gdy działania się zamykają.
KolejnÄ… opcjÄ… jest utrzymanie LinkedList
odniesień do wszystkich otwartych działań, które są statycznie dostępne zewsząd(być może za pomocą słabych odniesień). Po wylogowaniu uzyskam dostęp do tej listy i powtórzę wszystkie wcześniej otwarte działania, wywołując finish()
na każdej z nich. Prawdopodobnie wkrótce zacznę wdrażać tę metodę.
Czy jest sposób na aby to osiągnąć, użyj Intent
lub ustawień manifestu, czy też moja druga opcja, utrzymywanie LinkedList
otwartych działań jest najlepszą opcją? A może jest inna opcja, której kompletnie nie dostrzegam?
18 answers
Mogę zaproponować Ci inne podejście IMHO bardziej solidne.
Zasadniczo musisz wysłać wiadomość wylogowania do wszystkich swoich działań, które muszą pozostać w stanie zalogowanym. Możesz więc użyć sendBroadcast
i zainstalować BroadcastReceiver
we wszystkich swoich ustawieniach.
CoÅ› takiego:
/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);
Odbiorca (zabezpieczona aktywność):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**snip **/
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.package.ACTION_LOGOUT");
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive","Logout in progress");
//At this point you should start the login activity and finish this one
finish();
}
}, intentFilter);
//** snip **//
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-01 02:33:32
Wydaje się, że nowy programista Androida spędza dzień badając ten problem i czytając wszystkie te wątki StackOverflow. Jestem teraz nowo zainicjowany i zostawiam tu ślad mojego pokornego doświadczenia, aby pomóc przyszłemu pielgrzymowi.
Po pierwsze, nie ma oczywistego lub natychmiastowego sposobu, aby to zrobić na podstawie moich badań (as of September 2012).
można by pomyśleć, że możesz proste startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)
ale Nie .
Możesz wykonać startActivity(new Intent(this, LoginActivity.class))
za pomocÄ… FLAG_ACTIVITY_CLEAR_TOP
- a to spowoduje, że framework będzie przeszukiwał stos, znajdź wcześniejszą pierwotną instancję LoginActivity, odtworz ją i wyczyść resztę stosu (w górę). A ponieważ Logowanie jest prawdopodobnie na dole stosu, masz teraz pusty stos, a przycisk Wstecz po prostu opuszcza aplikację.
Ale - to działa tylko wtedy, gdy wcześniej pozostawiłeś oryginalną instancję LoginActivity żywą u podstawy stosu. Jeśli, podobnie jak wielu programistów, zdecydowałeś się finish()
, że LoginActivity
Po pomyślnym zalogowaniu się użytkownika, to nie jest już włączony podstawa stosu i semantyka FLAG_ACTIVITY_CLEAR_TOP
nie mają zastosowania ... w końcu tworzysz nową LoginActivity
na szczycie istniejącego stosu. Co prawie na pewno nie jest tym ,czego chcesz (dziwne zachowanie, w którym użytkownik może "cofnąć" swoje wyjście z logowania na poprzednim ekranie).
Więc jeśli masz wcześniej finish()
' d LoginActivity
, musisz zastosować jakiś mechanizm do wyczyszczenia stosu, a następnie uruchomić nowy LoginActivity
. Wygląda na to, że odpowiedź @doreamon
w tym wÄ…tku jest najlepszym rozwiÄ…zaniem (przynajmniej dla mojego skromne oko):
Https://stackoverflow.com/a/9580057/614880
Mocno podejrzewam, że trudne implikacje tego, czy zostawisz LoginActivity przy życiu, powodują wiele tego zamieszania.
Powodzenia.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:32
UPDATE
Metoda super finishAffinity()
pomoże zredukować kod, ale osiągnąć to samo. Zakończy bieżącą aktywność, jak również wszystkie działania w stosie, użyj getActivity().finishAffinity()
, jeśli znajdujesz się w fragmencie.
finishAffinity();
startActivity(new Intent(mActivity, LoginActivity.class));
ORYGINALNA ODPOWIEDŹ
Załóżmy, że LoginActivity -- > HomeActivity -->... --> SettingsActivity call signOut ():
void signOut() {
Intent intent = new Intent(this, HomeActivity.class);
intent.putExtra("finish", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
startActivity(intent);
finish();
}
Strona główna:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean finish = getIntent().getBooleanExtra("finish", false);
if (finish) {
startActivity(new Intent(mContext, LoginActivity.class));
finish();
return;
}
initializeView();
}
To działa dla mnie, mam nadzieję, że to jest pomocne również dla Ciebie. :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 02:54:55
Jeśli używasz API 11 lub wyższej, możesz spróbować tego: FLAG_ACTIVITY_CLEAR_TASK
--wygląda na to, że odnosi się dokładnie do twojego problemu. Oczywiście tłum pre-API 11 musiałby użyć jakiejś kombinacji sprawdzania wszystkich aktywności, jak sugeruje @doreamon, lub innej sztuczki.
(również uwaga: aby tego użyć musisz przejść w FLAG_ACTIVITY_NEW_TASK
)
Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("finish", true); // if you are checking for this in your other Activities
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 14:01:25
Nad tym też spędziłem kilka godzin ... i zgadzam się, że FLAG_ACTIVITY_CLEAR_TOP brzmi tak, jakbyś chciał: Wyczyść cały stos, z wyjątkiem uruchamianej aktywności, więc przycisk Wstecz wychodzi z aplikacji. Jednak jak wspomniał Mike Repass, FLAG_ACTIVITY_CLEAR_TOP działa tylko wtedy, gdy aktywność, którą uruchamiasz, jest już w stosie; gdy aktywności nie ma, flaga nic nie robi.
Co robić? Umieść działanie uruchamiane w stosie z FLAG_ACTIVITY_NEW_TASK , co sprawia, że ta aktywność jest początkiem nowego zadania na stosie historii. następnie Dodaj znacznik FLAG_ACTIVITY_CLEAR_TOP.Teraz, gdy FLAG_ACTIVITY_CLEAR_TOP znajdzie nową aktywność w stosie, będzie ona tam i zostanie wyciągnięta, zanim Wszystko inne zostanie wyczyszczone.
Oto moja funkcja wylogowania; parametr widoku jest przyciskiem, do którego funkcja jest dołączona.
public void onLogoutClick(final View view) {
Intent i = new Intent(this, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:18
Wiele odpowiedzi. Może ten też pomoże -
Intent intent = new Intent(activity, SignInActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
this.finish();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-16 11:53:12
Użyj tego to powinno być pomocne dla Ciebie. Lekko zmodyfikowana odpowiedź xbakesx.
Intent intent = new Intent(this, LoginActivity.class);
if(Build.VERSION.SDK_INT >= 11) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
} else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivity(intent);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 14:00:58
Przyjęte rozwiązanie nie jest poprawne, ma problemy, ponieważ używanie odbiornika nadawczego nie jest dobrym pomysłem na ten problem. Jeśli Twoja aktywność wywołała już metodę onDestroy (), nie otrzymasz receiver. Najlepszym rozwiązaniem jest posiadanie wartości logicznej na współdzielonych preferencjach i sprawdzanie jej w metodzie OnCreate () activty. Jeżeli nie powinno być wywołane, gdy użytkownik nie jest zalogowany, to Zakończ czynność. Oto przykładowy kod do tego. Tak proste i działa na każdy warunek.
protected void onResume() {
super.onResume();
if (isAuthRequired()) {
checkAuthStatus();
}
}
private void checkAuthStatus() {
//check your shared pref value for login in this method
if (checkIfSharedPrefLoginValueIsTrue()) {
finish();
}
}
boolean isAuthRequired() {
return true;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 09:58:49
Wybrana odpowiedź jest sprytna i podstępna. Oto jak to zrobiłem:
LoginActivity jest aktywnością roota zadania, ustawioną android: noHistory= "true" do niego w manifeście.xml; Jeśli chcesz wylogować się z ustawień, możesz to zrobić jak poniżej:
Intent i = new Intent(SettingsActivity.this, LoginActivity.class);
i.addFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 13:19:14
Oto rozwiązanie, które wymyśliłem w mojej aplikacji.
W moim LoginActivity, po pomyślnym przetworzeniu loginu, uruchamiam następny inaczej w zależności od poziomu API.
Intent i = new Intent(this, MainActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
startActivity(i);
finish();
} else {
startActivityForResult(i, REQUEST_LOGIN_GINGERBREAD);
}
Następnie w moim login Activity ' s onActivityForResult method:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB &&
requestCode == REQUEST_LOGIN_GINGERBREAD &&
resultCode == Activity.RESULT_CANCELED) {
moveTaskToBack(true);
}
Wreszcie, po przetworzeniu wylogowania w jakiejkolwiek innej aktywności:
Intent i = new Intent(this, LoginActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
Kiedy na pierniku, sprawia, że jeśli nacisnę przycisk Wstecz od MainActivity, LoginActivity jest natychmiast Ukryty. Na plastrze miodu i Później, Właśnie kończę logowanie po przetworzeniu loginu i jest ono poprawnie odtworzone po przetworzeniu logowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 14:01:44
Sometime finish()
not working
Rozwiązałem ten problem z
finishAffinity()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-31 04:43:49
Rozpocznij swoją aktywność z StartActivityForResult i podczas wylogowania Ustaw wynik i zgodnie z Twoim wynikiem Zakończ swoją aktywność
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivityForResult(intent, BACK_SCREEN);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case BACK_SCREEN:
if (resultCode == REFRESH) {
setResult(REFRESH);
finish();
}
break;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog
.setTitle((String) getResources().getText(R.string.home));
alertDialog.setMessage((String) getResources().getText(
R.string.gotoHome));
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
setResult(REFRESH);
finish();
}
});
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
});
alertDialog.show();
return true;
} else
return super.onKeyDown(keyCode, event);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-15 12:50:34
Dostarczone rozwiązanie @ doreamon działa dobrze we wszystkich przypadkach z wyjątkiem jednego:
Jeśli po zalogowaniu, użytkownik ekranu logowania przechodzi bezpośrednio na środkowy ekran. np. W przepływie A->B->C, Przejdź jak: Login - > B - > C - > naciśnij skrót do domu. Użycie FLAG_ACTIVITY_CLEAR_TOP czyści tylko aktywność C, ponieważ dom (a) nie znajduje się w historii stosu. Naciśnięcie przycisku na ekranie doprowadzi nas z powrotem do B.
Aby rozwiązać ten problem, możemy zachować stos aktywności (Arraylist) i gdy dom jest wciśnięty, musimy zabić wszystkie działania w tym stosie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 11:19:00
Jest to możliwe poprzez zarządzanie flagą w SharedPreferences lub w aktywności aplikacji.
Po uruchomieniu aplikacji (na ekranie powitalnym) Ustaw flagę = false; po wylogowaniu kliknij event Ustaw flagę true i w onresume() każdej aktywności sprawdź, czy flaga jest true, a następnie wywołaj finish ().
Działa jak czar:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 17:48:36
Po kliknięciu wylogowania możesz wywołać to
private void GoToPreviousActivity() {
setResult(REQUEST_CODE_LOGOUT);
this.finish();
}
OnActivityResult () poprzedniej aktywności wywołaj powyższy kod ponownie, dopóki nie zakończysz wszystkich działań.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 14:01:38
To mi pomogło:
// After logout redirect user to Loing Activity
Intent i = new Intent(_context, MainActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Add new Flag to start new Activity
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Staring Login Activity
_context.startActivity(i);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 12:14:29
Sugerowałbym inne podejście do tego pytania. Może nie jest najbardziej wydajny, ale myślę, że jest najłatwiejszy do zastosowania i wymaga bardzo mało kodu. Zapisanie kolejnego kodu w pierwszej aktywności (aktywność logowania, w moim przypadku) nie pozwoli użytkownikowi wrócić do wcześniej rozpoczętych działań po wylogowaniu.
@Override
public void onBackPressed() {
// disable going back to the MainActivity
moveTaskToBack(true);
}
Zakładam, że Login jest zakończony zaraz po zalogowaniu się użytkownika, więc nie może do niego wrócić później, naciskając przycisk Wstecz. Zamiast tego użytkownik aby wylogować się prawidłowo, należy nacisnąć przycisk Wyloguj się wewnątrz aplikacji. To, co ten przycisk Wyloguj zaimplementowałby, jest prostą intencją w następujący sposób:
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
Wszelkie sugestie sÄ… mile widziane.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-12 12:07:14
Jedną z opcji jest sprawdzenie statusu zalogowanej aktywności onCreate I finish (), jeśli nie jest zalogowana. Nie podoba mi się ta opcja, ponieważ przycisk Wstecz będzie nadal dostępny do użycia, nawigując wstecz, gdy działania się zamykają.
To, co chcesz zrobić, to wywołać logout() I finish() w metodach onStop() lub onPause (). Spowoduje to zmuszenie Androida do wywołania OnCreate (), gdy aktywność zostanie przywrócona, ponieważ nie będzie już miała jej w stosie swojej aktywności. Więc zrób jak mówisz, w OnCreate() sprawdź status zalogowanego i prześlij do ekranu logowania, jeśli nie jesteś zalogowany.
Kolejną rzeczą, którą możesz zrobić, to sprawdzić status zalogowanego w onresume (), a jeśli nie jesteś zalogowany, Zakończ () i uruchom aktywność logowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 17:52:09