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

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

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

Я попытался открыть действие входа, установив его Intent флаги на FLAG_ACTIVITY_CLEAR_TOP, что, похоже, делает то, что описано в документации, но не достигает моей цели по размещению действия входа в нижнюю часть стека истории и предотвращению пользователя от вернуться к ранее просмотренным действиям, когда вы вошли в систему. Я также пробовал использовать android:launchMode="singleTop" для активности входа в манифест, но это тоже не достигает моей цели (и, похоже, все равно не имеет никакого эффекта).

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

Один из вариантов - иметь onCreate проверку состояния входа в систему и finish(), если вход не выполнен. Мне не нравится этот вариант, так как кнопка «Назад» по-прежнему будет доступна для использования, позволяя возвращаться назад, когда действия закрываются.

Следующий вариант - поддерживать LinkedList ссылок на все открытые действия, которые статически доступны отовсюду (возможно, с использованием слабых ссылок). При выходе из системы я получу доступ к этому списку и буду перебирать все ранее открытые действия, вызывая finish() для каждого из них. Я, наверное, скоро приступлю к реализации этого метода.

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

Есть ли способ добиться этого, используя Intent или настройки манифеста, или мой второй вариант, поддержание LinkedList открытых действий - лучший вариант? Или есть еще один вариант, который я полностью упускаю из виду?


person skyler    schedule 09.06.2010    source источник


Ответы (18)


Я могу предложить вам другой подход, ИМХО, более надежный. В основном вам нужно транслировать сообщение о выходе для всех ваших действий, которые должны оставаться в состоянии входа в систему. Таким образом, вы можете использовать sendBroadcast и установить BroadcastReceiver во всех ваших Actvities. Что-то вроде этого:

/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);

Получатель (защищенная активность):

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 **//
}
person Francesco Laurita    schedule 09.06.2010
comment
Это не кажется полезным. Только текущая самая активная активность сможет динамически регистрироваться для этих трансляций. И событие выхода из системы происходит из-за самого действия, так что это избыточно. Нажатие Back в этот момент вернет вас к предыдущему действию, о котором не будет известно о выходе из системы. - person Christopher Orr; 15.12.2010
comment
@Christopher, каждое действие регистрируется для трансляции при создании. Когда он переходит в фоновый режим (т. Е. Новое действие попадает в верхнюю часть стека), вызывается его onStop (), но он все еще может принимать широковещательные сообщения. Вам просто нужно убедиться, что вы вызываете unregisterReceiver () в onDestroy (), а не в onStop (). - person Russell Davis; 29.12.2010
comment
Работает ли это, если действие где-то в стеке было отключено ОС для восстановления памяти? Т.е. будет ли система считать, что это действительно завершено после отправки вышеупомянутой трансляции, и не будет ли воссоздавать ее при нажатии кнопки возврата? - person Jan Żankowski; 07.06.2011
comment
Хотя это действительно кажется элегантным решением, важно отметить, что это не синхронно. - person Che Jami; 25.10.2011
comment
@Che Jami: так что будет синхронно? - person IgorGanapolsky; 18.03.2012
comment
@ Игорь Ганапольский: может, я придумаю. Предположим, у вас есть действие входа и действие A, B, C. Стек задач будет иметь вид Login- ›A-› B- ›C. И действия A, B и C защищены. Как только вы в действии C получили намерение выйти из системы. А и Б тоже получили. Тогда каков порядок их onReceive по этим трем действиям? - person Yeung; 10.04.2013
comment
Хорошее решение, но вместо использования регистрации широковещательного приемника, как описано в приведенном выше коде, вы должны использовать LocalBroadcastManager.getInstance (this) .registerReceiver (...) и LocalBroadcastManager.getInstance (this) .unregisterReceiver (..) . В противном случае ваше приложение может получать намерения от любого другого приложения (проблема безопасности) - person Uku Loskit; 06.05.2013
comment
Что делать, если активность в backstack прекращается системой (нехватка памяти), и это действие не будет получать широковещательную рассылку. Но это действие останется в обратной записи стека. Не уверен, что это самое пуленепробиваемое решение. - person Warlock; 03.10.2013
comment
Слишком много кода для довольно простой (для пользователя) функции. - person Subin Sebastian; 08.11.2013
comment
@Warlock Вы правы. Ловушка этого подхода - когда Activity в заднем стеке уничтожается системой (может произойти по разным причинам, например, из-за отмеченного сценария нехватки памяти). В этом случае экземпляр Activity не будет принимать трансляцию. Но система по-прежнему будет перемещаться по этому Activity, воссоздавая его. Это можно проверить / воспроизвести, включив настройку разработчика Don't Keep Activities. - person Eric Schlenz; 30.01.2014
comment
Этот подход с советом @Uku Loskit делает это за меня. Он также охватывает проблемы, указанные пользователем Майком Репасом (относительно вызова startActivity (new Intent (this, LoginActivity.class)) с помощью FLAG_ACTIVITY_CLEAR_TOP). - person user1987392; 29.05.2014
comment
Старый пост, но один случай, когда это не удается, - это если действие переходит в спящий режим (Android сериализует его для экономии памяти). Если это произойдет, активность не сможет принять широковещательную рассылку и закроется. Для тестирования установите флаг «Не сохранять активности» в настройках разработчиков. Есть ли альтернатива, вы пробовали связанныйList? - person toidiu; 04.02.2015
comment
как заявил @Warlock, это решение не будет работать во всех ситуациях. См. Мое базовое решение ниже для рабочего примера - person Yekmer Simsek; 09.07.2015
comment
Вероятно, этого можно было бы достичь с помощью finishAffinity - stackoverflow.com/a/16825302/206292 - person Krishnaraj; 27.10.2015
comment
Я использовал Отто вместо широковещательного приемника - person Odaym; 12.03.2016
comment
Это взлом, который завершится неудачей, как только ваш backstack будет уничтожен для освобождения памяти. - person Blago; 11.02.2018
comment
должны ли мы делать одно действие и расширять из него все действия, чтобы мы писали код только один раз? - person has19; 27.07.2018

Кажется, это обряд посвящения, когда новый программист Android проводит день, исследуя эту проблему и читая все эти темы StackOverflow. Сейчас я новичок и оставляю здесь след своего скромного опыта, чтобы помочь будущему паломнику.

Во-первых, согласно моему исследованию, не существует очевидного или немедленного способа сделать это (as of September 2012). Вы могли бы подумать, что можете просто startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK), но нет.

Вы МОЖЕТЕ сделать startActivity(new Intent(this, LoginActivity.class)) с FLAG_ACTIVITY_CLEAR_TOP - и это заставит фреймворк искать вниз по стеку, находить ваш более ранний исходный экземпляр LoginActivity, воссоздавать его и очищать остальную часть (вверх) стека. А поскольку логин предположительно находится внизу стека, теперь у вас пустой стек, а кнопка «Назад» просто закрывает приложение.

НО - это работает только в том случае, если вы ранее оставили активным исходный экземпляр LoginActivity в основе вашего стека. Если, как и многие программисты, вы выбрали finish() этот LoginActivity после того, как пользователь успешно вошел в систему, тогда он больше не находится на основе стека и семантика FLAG_ACTIVITY_CLEAR_TOP не применяется ... вы в конечном итоге создаете новый LoginActivity поверх существующий стек. Это почти наверняка НЕ ​​то, что вы хотите (странное поведение, когда пользователь может «вернуться» из входа на предыдущий экран).

Итак, если вы ранее finish() использовали LoginActivity, вам необходимо разработать какой-то механизм для очистки вашего стека и последующего запуска нового LoginActivity. Похоже, что ответ @doreamon в этой ветке - лучшее решение (по крайней мере, на мой скромный взгляд):

https://stackoverflow.com/a/9580057/614880

Я сильно подозреваю, что непростые последствия того, оставите ли вы LoginActivity активным, вызывают большую путаницу.

Удачи.

person Mike Repass    schedule 17.09.2012
comment
Хороший ответ. Уловка FLAG_ACTIVITY_CLEAR_TOP, которую большинство людей советует использовать, просто не работает, если вы завершили LoginActivity. - person Konsumierer; 05.10.2012
comment
Спасибо за ответ. Другой сценарий похож на тот, когда есть сеанс (например, как fb), даже если мы не вызываем активность входа в систему, поэтому в стеке нет точки активности входа в систему. Тогда вышеупомянутый подход бесполезен. - person Prashanth Debbadwar; 28.04.2015

ОБНОВЛЕНИЕ

метод super finishAffinity() поможет уменьшить код, но добиться того же. Он завершит текущее действие, а также все действия в стеке, используйте getActivity().finishAffinity(), если вы находитесь во фрагменте.

finishAffinity(); 
startActivity(new Intent(mActivity, LoginActivity.class));

ОРИГИНАЛЬНЫЙ ОТВЕТ

Предположим, что 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();
}

Главная Деятельность:

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

Это работает для меня, надеюсь, что это будет полезно и для вас. :)

person thanhbinh84    schedule 06.03.2012
comment
Я думаю, ваше решение предполагает, что пользователь нажмет кнопку «Выход» и вернется только к одному действию (HomeActivity). Что, если у вас в стеке 10 занятий? - person IgorGanapolsky; 18.03.2012
comment
Если у вас есть 10 действий в верхней части HomeActivity, флаг FLAG_ACTIVITY_CLEAR_TOP поможет очистить их все. - person thanhbinh84; 20.03.2012
comment
Если вы выбрали finish () исходный экземпляр LoginActivity, то ЭТОТ ответ (@ doreamon) определенно правильный путь. Семантика _CLEAR_TOP работает только в том случае, если фреймворк может найти предыдущий экземпляр ниже вас в стеке - в противном случае нет кости. - person Mike Repass; 18.09.2012
comment
Это может работать, только если при запуске HomeActivity вы получаете OnCreate of HomeActivity. Простое начало домашней деятельности не обязательно воссоздает ее, если она уже не закончена или не уничтожена. Если HomeActivity не нужно воссоздавать, OnCreate не будет вызван, и после выхода из системы вы будете сидеть на своей домашней активности. - person topwik; 30.11.2012
comment
Это возможное решение, которое требует гораздо меньше кодирования простой (для пользователя) функции, такой как выход из системы. - person Subin Sebastian; 08.11.2013
comment
+1 Осмелюсь сказать, это ЕДИНСТВЕННЫЙ способ реализовать FLAG_ACTIVITY_CLEAR_TASK эффект очистки задачи в API уровня 10 или ниже! - person 9dan; 15.05.2014
comment
Что, если мне нужно перейти непосредственно к активности входа в систему, но я не хочу ее перезапускать. Могу я использовать CLEAR_TOP | SINGLE_TOP? Меня беспокоит эта ветка - person Sebek; 08.07.2014
comment
Если это так, просто удалите строку startActivity (new Intent (mContext, LoginActivity.class)), она отклонит вашу HomeActivity, и LoginActivity появится без перезапуска. Предположим, что вы не вызываете finish () перед запуском HomeActivity. - person thanhbinh84; 11.07.2014
comment
Флаг Intent.FLAG_ACTIVITY_CLEAR_TOP помогает очистить все действия, включая HomeActivity, поэтому метод onCreate () будет вызываться, когда вы снова запустите это действие. - person thanhbinh84; 18.11.2014
comment
@doraemon Это не поддерживается, если устройство ниже, чем honecomp, с уже закрытым LoginActivity, тогда оно не работает. - person Mohamed Ibrahim; 10.01.2015
comment
Не могли бы Вы уточнить. В чем твоя проблема? Я использую эту функцию с 2.2 по 4.2 и не вижу никаких проблем. - person thanhbinh84; 20.01.2015
comment
Это не распространяется на случай, когда HomeActivity не находится в backstack :) - person Marian Paździoch; 17.07.2015
comment
Он работает хорошо, но убедитесь, что вы не использовали launchMode = singleTop (в Manifest) для HomeActivity, иначе это не сработает. - person Narendra Singh; 16.02.2017

Если вы используете API 11 или выше, вы можете попробовать следующее: FLAG_ACTIVITY_CLEAR_TASK - кажется чтобы решить именно вашу проблему. Очевидно, что толпе, предшествовавшей API 11, пришлось бы использовать какую-то комбинацию, чтобы все действия проверяли дополнительную, как предлагает @doreamon, или какой-то другой трюк.

(Также обратите внимание: чтобы использовать это, вы должны передать 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();
person xbakesx    schedule 04.02.2013
comment
Работает как шарм. Большое спасибо! Поскольку я разрабатываю min API 14, это единственное, что нужно реализовать. - person AndyB; 09.01.2016
comment
Я думаю, нам не нужен FLAG_ACTIVITY_CLEAR_TOP при использовании этого решения для LoginActivity. - person Bharat Dodeja; 16.05.2016
comment
Я думаю, что просто finish(); выполнит работу по предотвращению возврата после выхода из системы. Зачем нужно устанавливать флаги? - person Pankaj; 05.06.2017
comment
Это создает исключение. Для вызова startActivity () вне контекста Activity требуется флаг FLAG_ACTIVITY_NEW_TASK - person Aman; 08.01.2019

Я тоже потратил на это несколько часов ... и согласен, что FLAG_ACTIVITY_CLEAR_TOP звучит так, как вам нужно: очистить весь стек, за исключением запущенного действия, поэтому кнопка «Назад» закрывает приложение. Однако, как упоминал Майк Репасс, FLAG_ACTIVITY_CLEAR_TOP работает только тогда, когда действие, которое вы запускаете, уже находится в стеке; когда активности нет, флаг ничего не делает.

Что делать? Поместите запускаемое действие в стек с помощью FLAG_ACTIVITY_NEW_TASK, что делает это действие - начало новой задачи в стеке истории. Затем добавьте флаг FLAG_ACTIVITY_CLEAR_TOP.

Теперь, когда FLAG_ACTIVITY_CLEAR_TOP найдет новое действие в стеке, оно будет там и будет извлечено до того, как все остальное будет очищено.

Вот моя функция выхода из системы; Параметр View - это кнопка, к которой прикреплена функция.

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();
}
person christinac    schedule 19.06.2013
comment
Не будет работать с API ‹= 10, поскольку FLAG_ACTIVITY_CLEAR_TASK еще не добавлен - person Youans; 12.11.2013
comment
@christinac Вы говорите о FLAG_ACTIVITY_CLEAR_TOP, а в вашем фрагменте кода есть FLAG_ACTIVITY_CLEAR_TASK; что тогда действительно? - person Marian Paździoch; 17.07.2015

Множество ответов. Может быть, это тоже поможет-

Intent intent = new Intent(activity, SignInActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
this.finish();

Версия Котлина-

Intent(this, SignInActivity::class.java).apply {
    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.also { startActivity(it) }
finish()
person Gulshan    schedule 22.07.2015

Используйте это, это должно быть вам полезно. Слегка измененный ответ 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);
person Mohamed Ibrahim    schedule 25.06.2014

Принятое решение неверно, у него есть проблемы, так как использование широковещательного приемника не является хорошей идеей для решения этой проблемы. Если ваша активность уже вызвала метод onDestroy (), вы не получите получателя. Лучшее решение - иметь логическое значение в ваших общих предпочтениях и проверять его в методе onCreate () вашей активности. Если он не должен вызываться, когда пользователь не вошел в систему, завершите действие. Вот пример кода для этого. Так просто и работает для любых условий.

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;
}
person Yekmer Simsek    schedule 09.07.2015
comment
Прошли годы, но я верю, что сделал и то, и другое. Каждое действие расширяет LoggedInActivity, которое проверяет состояние входа пользователя в onCreate (). LoggedInActivity также прослушивал трансляцию выхода пользователя из системы и делал все необходимое, чтобы отреагировать на это. - person skyler; 09.07.2015
comment
более вероятно, вам следует поместить checkAuthStatus в метод onResume(). Потому что, когда вы нажимаете кнопку «Назад», действие с большей вероятностью будет возобновлено, а не создано. - person maysi; 04.09.2015
comment
@maysi Спасибо за предложение, да, эта кнопка возврата тоже будет работать правильно, я обновил запись - person Yekmer Simsek; 07.09.2015

Иногда finish() не работает

Я решил эту проблему с помощью

finishAffinity()

person AJay    schedule 31.08.2017

Вот решение, которое я придумал в своем приложении.

В моем LoginActivity после успешной обработки входа в систему я запускаю следующий по-разному, в зависимости от уровня 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);
}

Затем в моем методе LoginActivity onActivityForResult:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB &&
        requestCode == REQUEST_LOGIN_GINGERBREAD &&
        resultCode == Activity.RESULT_CANCELED) {
    moveTaskToBack(true);
}

Наконец, после обработки выхода из любого другого действия:

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

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

person seastland    schedule 04.11.2013
comment
У меня это не работает. В моем случае я использовал фрагментарную активность. Метод Onactivityresult не вызывается. - person Mohamed Ibrahim; 10.01.2015

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

@Override
public void onBackPressed() {
    // disable going back to the MainActivity
    moveTaskToBack(true);
}

Я предполагаю, что LoginActivity завершается сразу после того, как пользователь входит в систему, поэтому он не может вернуться к нему позже, нажав кнопку «Назад». Вместо этого пользователь должен нажать кнопку выхода внутри приложения, чтобы выйти из системы должным образом. Эта кнопка выхода из системы будет реализовывать простое намерение, как показано ниже:

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

Все предложения приветствуются.

person Nil    schedule 12.02.2018

Выбранный ответ умный и хитрый. Вот как я это сделал:

LoginActivity - это корневое действие задачи, установите для него android: noHistory = "true" в Manifest.xml; Скажем, вы хотите выйти из SettingsActivity, вы можете сделать это, как показано ниже:

    Intent i = new Intent(SettingsActivity.this, LoginActivity.class);
    i.addFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
            | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(i);
person t-gao    schedule 18.12.2014

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

     // 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);
person Preetansh    schedule 24.06.2015
comment
Не могли бы вы подробнее рассказать о своем ответе, добавив еще немного описания предлагаемого вами решения? - person abarisone; 24.06.2015

Начните свою деятельность с StartActivityForResult, и пока вы выходите из системы, установите свой результат и в соответствии с вашим результатом завершите свою деятельность

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

}
person Eby    schedule 15.12.2010

Предоставленное @doreamon решение отлично работает во всех случаях, кроме одного:

Если после входа в систему пользователь экрана Killing Login перешел прямо на средний экран. например В потоке A-> B-> C перемещайтесь как: Вход в систему -> B -> C -> Нажмите ярлык на главную. Использование FLAG_ACTIVITY_CLEAR_TOP очищает только активность C, поскольку Home (A) не находится в истории стека. Нажатие Back на экране A приведет нас обратно к B.

Чтобы решить эту проблему, мы можем сохранить стек действий (Arraylist), и при нажатии кнопки home мы должны убить все действия в этом стеке.

person Surendra Kumar    schedule 20.06.2014

Это возможно, установив флаг в SharedPreferences или в Application Activity.

При запуске приложения (на экране-заставке) установите флаг = false; В событии Logout Click просто установите флаг true, а в OnResume () каждого действия проверьте, установлен ли флаг true, затем вызовите finish ().

Работает как часы :)

person MrDumb    schedule 31.07.2014

при нажатии кнопки «Выход» вы можете вызвать это

private void GoToPreviousActivity() {
    setResult(REQUEST_CODE_LOGOUT);
    this.finish();
}

onActivityResult () предыдущего действия вызовите этот код еще раз, пока не завершите все действия.

person Mak    schedule 23.02.2012
comment
Это означает, что он должен проходить через все действия линейно, вместо того, чтобы транслировать finish () все сразу? - person IgorGanapolsky; 18.03.2012
comment
@ Игорь Г. да, это альтернативный способ сделать финиш последовательно - person Mak; 20.03.2012

Один из вариантов состоит в том, чтобы onCreate каждого действия проверял состояние входа в систему и finish (), если вход не выполнен. Мне не нравится этот вариант, так как кнопка «Назад» по-прежнему будет доступна для использования, позволяя возвращаться назад, когда действия закрываются.

Что вы хотите сделать, так это вызвать logout () и finish () в ваших методах onStop () или onPause (). Это заставит Android вызывать onCreate () при возобновлении активности, поскольку она больше не будет находиться в стеке активности. Затем сделайте, как вы говорите, в onCreate () проверьте статус входа в систему и перейдите к экрану входа в систему, если вы не вошли в систему.

Еще одна вещь, которую вы можете сделать, - это проверить статус входа в систему в onResume (), и, если вы не вошли в систему, finish () и запустить активность входа в систему.

person Ricardo Villamil    schedule 09.06.2010
comment
Я бы предпочел не выходить из системы при каждой паузе или остановке активности. Кроме того, приложение инициирует выход из системы или вход в систему, поэтому мне действительно не нужно проверять, вошел ли в систему. - person skyler; 09.06.2010
comment
@ Рикардо: разве ваше решение не требует BroadcastReceiver? - person IgorGanapolsky; 18.03.2012