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

368

Мое приложение имеет следующие экраны потока:

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

Теперь у меня есть общая log out кнопка на каждом экране

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

Я хочу, чтобы, когда пользователь нажимал на кнопку выхода из системы (с любого экрана), все экраны были завершены, и Log inоткроется новый экран .

Я пытался почти все, FLAG_ACTIVITYчтобы добиться этого. Я также прошёл несколько ответов в stackoverflow, но не смог решить проблему. Мое приложение на Android 1.6, поэтому не может использоватьFLAG_ACTIVITY_CLEAR_TASK

Есть ли способ решить проблему?

Tanmay Mandal
источник
Вы запускаете вложенные действия с помощью startActivityForResult?
woodshy
Нет. Все действия начинаются с startActivity.
Tanmay Mandal
Я использую вложенные действия, в то время как cod выполняет finishaffinitytask () во вложенных действиях. это меняет поведение? как иногда я получаю результат доставки результата ResultInfo при запуске finishaffinitytask.
Рипал Тамболи
Пожалуйста, проверьте этот ответ, он, несомненно, поможет вам stackoverflow.com/a/25159180/2732632
Кимми Дингра
3
Android 21 представил Activity.finishAndRemoveTask ().
Джозеф Джонсон

Ответы:

543

Использование:

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

Это очистит все действия сверху дома.

Предполагая, что вы завершаете экран входа в систему, когда пользователь входит в систему и создается домашняя страница, а затем все экраны с 1 по 5 поверх этого. Код, который я разместил, вернет вас на главный экран и завершит все остальные действия. Вы можете добавить дополнительное в намерение и прочитать его на домашнем экране, а также завершить его (возможно, снова запустить экран входа в систему или что-то еще).

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

Надеюсь это поможет.

Дарко
источник
Пользователь показывает свой первый экран как домашний экран, вот в чем основная проблема.
Tanmay Mandal
Хорошо, так как у меня есть мой ответ, вам нужно вернуться на домашний экран и закончить его. поэтому процесс вызывает намерение выше с любого экрана. получите намерение на главном экране и сразу же начните входить в систему и завершите работу после метода startActivity. Вы также можете переопределить ожидающую анимацию для нуля для входов и выходов, чтобы она не показывала переход (я делаю это, потому что он чувствует себя немного быстрее). Так что это должно работать нормально для того, что вам нужно.
DArkO
10
Вместо того, чтобы объявить активность как singleInstance, рассмотрите возможность использованияFLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP в качестве флагов для Намерения. Это завершит промежуточные действия и начнет (или вернет на передний план) желаемое действие.
CommonsWare
13
@ CommonsWare Добавление intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);к моим действиям не помогло мне. Оно не завершило промежуточные действия. Когда я нажимаю обратно с экрана входа в систему, я вижу предыдущие действия. Вот мой код 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
этот код очищает только верхний стек действий для очистки всех действий intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
Аджай Венугопал
318

Вы можете попробовать Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK. Это полностью очистит все предыдущие действия и начнет новую деятельность.

Конг Кен
источник
11
Правильное решение, но только API 11+
riwnodennyk
Я использовал этот дополнительный флаг, так как он не вызывает задержку при отображении основного действия (он не перезапускается, поэтому работает намного быстрее).
Маурицио
2
@riwnodennyk почему API 11+?
Мухаммед Бабар
17
Используйте IntentCompat.FLAG_ACTIVITY_CLEAR_TASK для версий до 11
Стивен Пена
2
@ono Да. Это должно быть все, что вам нужно. Убедитесь, что режим запуска вашей целевой активности установлен в манифесте как «singleTask».
Стивен Пена
137

Прежде чем запускать новую активность, просто добавьте следующий код:

finishAffinity();

Или, если вы хотите, чтобы он работал в предыдущих версиях Android:

ActivityCompat.finishAffinity(this);
Henrique
источник
12
ActivityCompat.finishAffinity (это); Вызывает activity.finish () для API <16. Так что это не сработает.
Амир Абро
1
@ Beto Caldas, я сам подтвердил исходный код, он не будет работать для API <16, как упомянул AamirAbro. Он просто завершит действие, которое вы передаете по API <16.
HendraWD
39

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

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

Приведенный выше код очищает все действия, кроме LoginActivity. Затем поместите следующий код в LoginActivity's' onCreate(...), чтобы прослушивать, когда LoginActivityвоссоздается и передается сигнал 'EXIT':

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

Почему создание кнопки выхода в Android так сложно?

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

Разработчики ОС Android хотят, чтобы ваша программа выдерживала неожиданное отключение и отключение телефона, а когда пользователь перезапускает программу, он начинает с того места, на котором остановился. Таким образом, пользователь может получить телефонный звонок, пока он использует ваше приложение, и открыть карты, которые требуют освобождения вашего приложения для получения дополнительных ресурсов.

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

Эрик Лещинский
источник
31
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Это будет работать для всех версий Android. Где IntentCompatкласс добавлен в библиотеку поддержки Android.

драгоценный камень
источник
IntentCompat.FLAG_ACTIVITY_CLEAR_TASKне распознается, используйте Intentвместо IntentCompat.
CoolMind
30

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

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

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

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

Аристо Майкл
источник
24

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

Для API 16+ используйте

finishAffinity();

Для ниже 16, используйте

ActivityCompat.finishAffinity(YourActivity.this);

Надеюсь, поможет!

Акшай Тару
источник
21

С сайта developer.android.com :

public void finishAffinity ()

Добавлено в API уровень 16

Завершите это действие, а также все действия непосредственно под ним в текущей задаче, которые имеют ту же привязку. Это обычно используется, когда приложение может быть запущено для другой задачи (например, из ACTION_VIEW типа контента, который он понимает), и пользователь использовал навигацию вверх для переключения из текущей задачи и в свою собственную задачу. В этом случае, если пользователь перешел к каким-либо другим действиям второго приложения, все они должны быть удалены из исходной задачи как часть переключения задачи.

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

gmrl
источник
19

На заметку, полезно знать
Этот ответ работает ( 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();

тогда как это не работает

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

.setFlags() заменяет любые предыдущие флаги и не добавляет новые флаги, пока.addFlags() делает.

Так что это тоже будет работать

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Джон
источник
Отличное объяснение разницы между setFlag и addFlag, спасибо
Pelanes
13

Если ваше приложение имеет минимальную версию SDK 16, то вы можете использовать finishAffinity ()

Завершите это действие, а также все действия непосредственно под ним в текущей задаче, которые имеют ту же привязку.

Для меня это работа. На экране Top Payment удалите все бэк-стеки,

@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

Решение, которое я реализовал для этого (я думаю, что где-то нашел его в Stack Overflow, но я не помню, так что спасибо тому, кто сделал это в первую очередь):

Из любой вашей деятельности сделайте это:

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

Затем в вашей LoginActivity перезаписать onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Энди
источник
3
Обычно это очень плохая идея, хотя она может сработать, она вводит точку контакта, которая может сломаться в будущем, и ее будет трудно отлаживать. Я говорю вам из опыта :)
Мартин Маркончини
10

Для кнопки выхода из системы на последнем экране приложения используйте этот код на слушателе кнопки выхода из системы, чтобы завершить все открытые предыдущие действия, и ваша проблема решена.

{
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
Amrit
источник
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
почему FLAG_ACTIVITY_CLEAR_TASK дважды?
Choletski
1
Насколько я понимаю, .setFlags заменяет предыдущие флаги и не добавляет никаких флагов. Я полагаю, что вы хотели использовать .addFlags? Вызвать весь код выше i1.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); стирается
iOSAndroidWindowsMobileAppsDev
addFlags работает для меня
Джамиль
1
setFlagsзаменит все предыдущие, поэтому последний setFlagsдействителен, предыдущие заменяются. Так что вам не нужно звонитьi1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mtrakal
8

у меня есть та же проблема, которую вы можете использовать IntentCompat, как это:

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

этот код работает для меня.

Android api 17

Аднан Абдолла Заки
источник
8

В моем случае я использую finishAffinity()функцию в последнем действии как:

finishAffinity()
startHomeActivity()

Надеюсь, это будет полезно.

Djek-Гриф
источник
7

вместо использования finish()просто использоватьfinishAffinity();

Хитеш Кушва
источник
1
Хороший ответ, но требует API 16
Акшай Тару
6

Войти-> Главный экран-> Экран 1-> Экран 2-> Экран 3-> Экран 4-> Экран 5

на экране 4 (или любой другой) ->

StartActivity (Войти)
с
FLAG_ACTIVITY_CLEAR_TOP

Пламен Николов
источник
2
Когда я нажимаю кнопку «Назад», все предыдущие действия отображаются в том порядке, в котором они были. Эти действия должны быть закрыты, при нажатии кнопки выхода из системы в стеке будет только одно действие, и это будет действие входа в систему. Экран входа в систему. Пользователь запускается с домашнего экрана.
Tanmay Mandal
6

для API> = 15 до API 23 простое решение.

 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);
Камаль Бункар
источник
Разработайте свой ответ, чтобы каждый мог извлечь из этого пользу.
Шубхамой
5

Если вы используете startActivityForResult()в своих предыдущих действиях, просто переопределите OnActivityResult()и вызовите finish();метод внутри него во всех действиях .. Это сделает работу ...

ngesh
источник
Нет, я использую startActivityтолько.
Tanmay Mandal
Будет трудно поддерживать onActivityResultкаждый вид деятельности. Я выполнил предложение DArkO и достиг своей цели и благодарю за помощь.
Танмей Мандал
3

Когда пользователь нажмет на кнопку выхода, напишите следующий код:

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

А также, когда после входа в систему, если вы вызываете новую деятельность, не используйте finish ();

Nikki
источник
2

Проще говоря, когда вы выходите из экрана входа в систему, а не после завершения экрана входа в систему.

И затем во всех последующих действиях используйте это для выхода из системы:

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

Работает отлично.

Асад Рао
источник
1

Если вы вошли в систему пользователя screen 1и оттуда вы переходите на другие экраны, используйте

Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Габриэль Негут
источник
Когда я нажимаю кнопку «Назад», все предыдущие действия отображаются в том порядке, в котором они были. Эти действия должны быть закрыты, при нажатии кнопки выхода из системы в стеке будет только одно действие, и это будет действие входа в систему.
Tanmay Mandal
Если вы хотите это поведение, вы должны переопределить onKeyDownи onBackPressed(или onKeyDown, если вы хотите поддерживать версии Android <2.0) в каждом из ваших действий (кроме входа в систему), и startActivity(login)там, как показано выше.
Габриэль Негут
У меня есть кнопка, которая выводит меня на экран входа в систему и завершает все действия в стеке. Возможно ли это?
Tanmay Mandal
1

Я нашел этот путь, он очистит всю историю и выйдет

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

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

Для API 16+ используйте

finishAffinity ();

Для ниже 16, используйте

ActivityCompat.finishAffinity (YourActivity.this);

Надеюсь, поможет!

shareedit ответил 27 мая '18 в 8:03

Акшай Тару

Самуэль Кироз
источник
0

Я нашел это решение для работы на любом устройстве, несмотря на уровень API (даже для <11)

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
priyankvex
источник
0

Лучший способ закрыть все предыдущие действия и очистить память

finishAffinity()
System.exit(0);
Шивам Трипати
источник
0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
Кишан Соланки
источник