Android: удалите все предыдущие действия из заднего стека.


119

Когда я нажимаю кнопку « Выход» в своем профиле, я хочу, чтобы пользователь перешел на страницу входа , где ему нужно использовать новые учетные данные.

Следовательно, я использовал этот код:

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

в onButtonClickкнопке выхода.

Но проблема в том, что когда я нажимаю кнопку возврата устройства в Activity Login, я попадаю в ProfileActivity. Я ожидал, что приложение закроется, когда я нажму кнопку возврата устройства в LoginActivity.

Что я делаю не так?

Я также добавил android:launchMode="singleTop"в манифест для моего LoginActivity

Спасибо


@GauravVashisth Я просто следил за этим решением stackoverflow.com/questions/5794506/…
Archie.bpgc

@ abbas.aniefa Это решение я немного сложнее. Это единственный способ очистить весь задний стек. Поскольку у меня более 30 мероприятий, я должен написать этот код трансляции для всех из них
Archie.bpgc

попробуйте тогда, stackoverflow.com/questions/10961481/… . Использование Broadcast - лучшее решение.
abbas.aniefa

другой подход, который вы можете использовать для выхода из системы, после выхода из системы сохраните один флаг в общих настройках и в каждом методе onRestart () действия вы можете проверить значение этой переменной, если для него установлено значение true, вы можете завершить текущее действие. поэтому независимо от того, сколько действий открыто в backgroud. это закончило бы всю вашу деятельность.
Hiren Dabhi

Ваш исходный код действительно работает для уровня API 11 или выше с настройкой. Вам просто нужно соединить флаги за один вызов: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);я получил ответ на этот вопрос: stackoverflow.com/questions/3473168/…
jokeefe

Ответы:


304

Предлагаемое здесь решение сработало для меня:

Ява

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Котлин

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

Однако для этого требуется уровень API> = 11.


Ребят, читайте документацию. FLAG_ACTIVITY_CLEAR_TASKЭто официальный способ получить. Не нужно менять все действия в приложении.
AlikElzin-kilaka

Это не работает для уведомлений stackoverflow.com/questions/24873131/…
Сэм

У меня minAPI = 16, поэтому у меня все работает отлично. Однако я заметил, что выполнение представления немного медленнее с API> 21 и плавно с API <21. Кто-нибудь сталкивается с такой же проблемой?
Red M

1
Это создаст новую задачу для действий
Рохит

@kgiannakakis Несомненно, решение работает, если у нас есть только одна задача (стек Activity Back), но когда у нас несколько задач (стек Activity), оно не работает. ex- скажем, у меня есть четыре действия для моего приложения A, B, C и D. Предположим, у меня есть два стека активности A-> B-> C (фон) и D-> A-> B (передний план) и If I вызовите действие A из моего текущего стека (D-> A-> B) с фильтром намерений, что вы предложили, что произойдет, очистите мой текущий стек (D-> A-> B) и откройте действие A, и когда я верну его, закройте приложение, но если я нажму кнопку недавнего приложения, я увижу там две задние стопки моего приложения.
Рахул Парета

31

Вот одно из решений, позволяющих очистить все действия вашего приложения при использовании кнопки выхода.

Каждый раз, когда вы запускаете Activity, запускайте его так:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

Если вы хотите закрыть все приложение, сделайте следующее:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL - это последняя глобальная переменная с уникальным целым числом, сигнализирующая о том, что вы хотите закрыть все действия.

Затем определите onActivityResult(...)обратный вызов каждого действия, чтобы, когда действие возвращается со значением RESULT_CLOSE_ALL, оно также вызывает finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Это вызовет каскадный эффект, который закроет все ваши действия.

Однако это взлом, и он используется startActivityForResultне предназначенным для этого способом.

Возможно, лучший способ сделать это - использовать широковещательные приемники, как показано здесь:

При выходе из системы очистить стек истории активности, не позволяя кнопке «назад» открывать Активы только для входа в систему.

См. Также эти темы для других методов:

Android: очистить задний стек

Завершить все предыдущие действия


4
Возможно ли это, когда у вас около 30 заданий по истории ??
Ракеш Гондалия

4
должно быть. Но если у вас есть 30 занятий в истории, возможно, вам стоит подумать об изменении дизайна. 30 кажется многовато, и Android может убить их сам.
Anup Cowkur

1
Это кажется плохим способом сделать это. Вопрос ответа @RakeshGondaliya кажется законным. 30 может быть просто числом, представляющим «большое» количество занятий. Этот ответ выглядит лучше: stackoverflow.com/a/3008684/243709
Аман Алам,

Это отличный ответ. Вы также можете использовать библиотеку EventBus для отправки событий своим действиям в backstack. github.com/greenrobot/EventBus
Стэн

Лучше использовать простой флаг «Intent.FLAG_ACTIVITY_CLEAR_TOP» с намерением
Навин Рао,

18

Чтобы полностью очистить стек действий, вы хотите создать новый стек задач с помощью TaskStackBuilder, например:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

Это не только создаст новый чистый стек задач, но и обеспечит правильное функционирование кнопки «вверх», если ваша LoginActivity имеет родительскую активность.


1
Это лучший способ сделать это.
Пол Берк,

FLAG_ACTIVITY_NEW_TASKили finishAffinity()не работал у меня. Только этот ответ решил цель.
TM

Если я выхожу из приложения с помощью кнопки «Назад» и возвращаюсь с помощью значка приложения, оно открывается в действии, которое я назвал этим методом. Так что у меня не работает.
Tgo1014

17

finishAffinity()добавлено в API 16. Используется ActivityCompat.finishAffinity()в предыдущих версиях. Когда вы запустите любое действие с использованием намерения и завершите текущее действие. Теперь используйте ActivityCompat.finishAffinity()вместо этого finish(). он завершит всю сложенную активность ниже текущей. Он отлично работает для меня.


3
Это на самом делеActivityCompat.finishAffinity()
Берга

finishAffinity()также завершает текущее действие со всеми действиями, присутствующими в заднем стеке того же соответствия.
Нирадж Севани 02

10

Что сработало для меня

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

5

Одно из возможных решений, которое я могу вам предложить, - это добавить android:launchMode="singleTop"в манифест для моей ProfileActivity . и при нажатии кнопки выхода вы можете выйти из системы, снова запустив LoginActivity. при выходе из системы вы можете вызвать это.

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

Я сделал это, вот что произошло: когда я нажимаю кнопку «Назад», я попадаю в Activty, откуда я пришел в
ProfileActivity

Это может произойти из-за того, что u перешел в ProfileActivity, вызвав новое намерение, а не вызвав finish (); Как вы попадаете в ProfileActivity из других видов деятельности, кроме LoginActivty?
Android

Я пересекаю тот же вопрос. Я думаю, что это не сработает, если намерение входа в систему было уничтожено системой, скажем, из-за отсутствия памяти.
user1914692 08

5

Для API 11+ вы можете использовать Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKэто так:

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

Он полностью очистит все предыдущие действия и начнет новую деятельность.


4

Вы можете попробовать finishAffinity(), он закрывает все текущие действия и работает на Android 4.1 и выше.


1
finishAffinity () добавлено в API 16. Используйте ActivityCompat.finishAffinity () в предыдущей версии. У меня работает нормально.
Анураг Шривастава

2

Я тоже столкнулся с той же проблемой ..

в активности входа в систему, что я делаю.

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

при выходе

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

Это работает хорошо, но когда я нахожусь в ActivityLoggedIn, свертываю приложение и нажимаю значок кнопки запуска на панели приложений, MainActivity запускается снова: - / я использую флаг

android:LaunchMode:singleTask 

для MainActivity.


2

Используйте следующее для activity

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

удалить CLEAR_TASK флаг для использования фрагмента.

Я надеюсь, что это может пригодиться некоторым людям.


1

Просто держи

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

4
Это не работает. Я все еще могу перейти в ProfileActivity, используя кнопку «Назад»
Archie.bpgc

1

Ни один из флагов намерений у меня не работал, но вот как я это исправил:

Когда пользователь выходит из одного действия, мне приходилось транслировать сообщение из этого действия, затем получать его в действиях, которые я хотел закрыть, после чего я вызываю finish (); и это работает очень хорошо.


1

Попробуйте, это сработает:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();

1

На уровне API 11 или выше используйте FLAG_ACTIVITY_CLEAR_TASKи FLAG_ACTIVITY_NEW_TASKотметьте намерение, чтобы очистить весь стек активности.

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

0

Использовать это

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

вы знали setFlags и addFlags?
GvSharma


0

Продвинутый, повторно используемый Котлин:

Вы можете установить флаг напрямую, используя метод setter. В Kotlin orесть замена Java на побитовый или |.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Если вы планируете использовать это регулярно, создайте функцию расширения Intent

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Затем вы можете напрямую вызвать эту функцию перед запуском намерения

intent.clearStack()

Если вам нужна возможность добавления дополнительных флагов в других ситуациях, добавьте необязательный параметр в функцию расширения.

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.