Подтвердить что ты не робот

Как вернуться к последней запущенной деятельности при повторном запуске приложения после нажатия HOME?

Знакомый сценарий: у меня есть основное действие, которое запускает игру, когда нажата кнопка. Если пользователь нажимает кнопку "HOME", а затем снова запускает мое приложение, он должен быть представлен с игрой, что было последним при использовании приложения.

Однако, что происходит вместо этого, он снова получает основное действие. У меня такое ощущение, что Android создает еще один экземпляр MainActivity и добавляет его в стек для этого приложения, вместо того, чтобы просто выбирать все, что было наверху, потому что, если я нажму BACK после перезапуска приложения, я попаду в игру! И метод Main.onCreate вызывается каждый раз, вместо вызова GameActivity.onResume.

Мой AndroidManifest.xml в значительной степени "голые кости":

<activity android:name="MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="GameActivity" android:label="@string/app_name">
</activity>

Как вы можете видеть, ничего необычного.

И вот как запускается новая активность, очень просто:

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

В теории это должно работать в Android только "из коробки", так как ответ на очень похожий вопрос гласит: Поддержание стандартного приложения. Состояние состояния Back Back в Android (с использованием singleTask режим запуска), но это не так.

Я читал и перечитывал документацию по Activity, Task и Stacks и просматривал все связанные ответы в SO, но я не могу понять, почему такая простая настройка работает не так, как ожидалось.

4b9b3361

Ответ 1

О, я думаю, что нашел ответ.

Поскольку я запускал приложение с помощью IntelliJ, кажется, что он запускает приложение по-другому, чем пользователь, щелкнув виджет главного экрана. Это объяснялось в ответе на другой вопрос:

Это происходит из-за намерений, используемых для запуска приложения. Eclipse запускает приложение с использованием намерения без каких-либо действий и без категории. Launcher запускает приложение, используя намерение с android.intent.action.MAIN action и android.intent.category.LAUNCHER. Установщик запускает приложение с действием android.intent.action.MAIN и без категории.

Ссылка: Приложение всегда запускается из корневой активности, а не возобновляет фоновое состояние (известная ошибка)

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

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

Ответ 2

    @Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 
        // Activity was brought to front and not created, 
        // Thus finishing this will get us to the last viewed activity 
        finish(); 
        return; 
    } 

    // Regular activity creation code... 
} 

Ответ 3

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

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

Ответ 4

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

Мне понравился ответ Sachin, но иногда это давало мне ложные срабатывания, и я бы закончил свою деятельность, когда я этого не сделал. Надежным способом, который я обнаружил, чтобы воспроизвести такой ложный результат, является:

  • Запустите приложение с рабочего стола
  • Нажмите домой
  • Запустил приложение с домашнего экрана снова
  • Нажмите "назад", чтобы вернуться на главный экран.
  • Вернулся в приложение из "последних приложений"

Я начал искать способы проверки активности своей задачи и нашел ответы с помощью ActivityManager. Казалось, что это может сработать, но этот ответ указал на существование isTaskRoot, который представляет собой простой, элегантный способ обнаружения этого, который не дает ложных срабатываний, не требует специального разрешения и не использует методы, о которых говорится в документах, предназначенных для приложений для отладки и управления задачами и которые не поддерживаются для такого типа использования.

Ответ 5

Я понимаю, откуда вы, но я думаю, что os не хочет делать никаких предположений. Кроме того, есть проблема, когда ваше приложение было исправлено, потому что память нужна для чего-то еще. В этом случае он начнется с вашего MainActivity.

В зависимости от того, насколько сложна ваша игра, вы можете либо сохранить состояние в SharedPreferences, либо базу данных SqlLite в методе onPause() вашей активности. Затем onResume() вы можете восстановить пользователя до последнего состояния, которое может включать в себя "повторный запуск" вашей GameActivity.

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

Изменить: И я говорю о том, что наша ответственность как разработчиков показывать/гарантировать пользователю, что правильная активность отображается при возвращении в приложение. У вашей прикладной памяти всегда есть потенциал для восстановления, а затем андроид снова запустит действие, которое вы отметили с помощью MAIN и LAUNCHER. Сохраняя состояние (идентификатор активности), вы можете перенаправить их на эту активность из основного...

Ответ 6

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

LaunchActivity → MainActivtiy → SomeSubActivtiy

LaunchActivtiy проверяет только некоторые параметры и запускает MainActivtiy. Оказалось, что MainActivity необходимо запустить с помощью

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

Эта комбинация флагов MainActivity дает желаемое поведение.