Как вернуться к последним запущенным действиям при повторном запуске приложения после нажатия HOME? - PullRequest
23 голосов
/ 14 июня 2011

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

Однако вместо этого он снова получает действие Main . У меня такое ощущение, что 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 просто "из коробки", поскольку ответ на очень похожий вопрос гласит: Поддержание стандартного состояния активности стека в приложении в Android (с использованием режима запуска singleTask) , но это не так.

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

Ответы [ 6 ]

28 голосов
/ 15 мая 2012
    @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... 
} 
18 голосов
/ 14 июня 2011

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

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

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

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

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

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

2 голосов
/ 28 мая 2013

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

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

  1. Запустите приложение с домашнего экрана
  2. Пресса домой
  3. Снова запустил приложение с домашнего экрана
  4. Нажмите «назад», чтобы вернуться на главный экран
  5. Вернулся в приложение из «последних приложений»

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

2 голосов
/ 14 июня 2011

Самое простое решение - выписать предпочтение во время onPause или сериализовать ваше состояние в постоянный файл, а затем прочитать этот файл во время onResume в вашей основной точке входа Activity. Это действие перестроит состояние приложения и перезапустит правильное действие.

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

1 голос
/ 03 декабря 2011

Я решаю проблему с помощью следующего стека активности в моем приложении:

LaunchActivity -> MainActivtiy -> SomeSubActivtiy

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

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

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

1 голос
/ 14 июня 2011

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

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

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

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

...