Сохранение приложения в фоновом режиме в ответ на намерение

#android #background #timeout #android-intent

#Android #фон #тайм-аут #android-намерение

Вопрос:

У моего приложения Android истек тайм-аут бездействия. По истечении времени ожидания я возвращаю пользователя на экран «Вход», который (всегда) находится в заднем стеке. Мой класс входа android:launchMode="singleTop" настроен таким образом, что экземпляр, запущенный в backstack, всегда используется повторно.

Я запускаю это намерение по таймауту:

 Intent inactivityTimeout = new Intent(this, SignIn.class);
inactivityTimeout.putExtra(INTENT_EXTRA_INACTIVITY_TIMEOUT, true);
int flags = inactivityTimeout.getFlags();
flags = flags|FLAG_FROM_BACKGROUND|Intent.FLAG_ACTIVITY_CLEAR_TOP;
inactivityTimeout.setFlags(flags);
  

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

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

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

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

Кто-нибудь может предложить способ реализовать это в моем намерении (или в ответном действии?). Или я здесь упускаю что-то концептуальное? Спасибо!

Ответ №1:

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

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

Это позволяет сбросить таймер.

Комментарии:

1. Спасибо, Марк! Это очень полезно. Однако я по глупости упустил по крайней мере пару деталей: во-первых, время ожидания бездействия является локальным и сбрасывается всякий раз, когда пользователь выполняет какое-либо действие (для этого я использую onUserInteraction ()). Во-вторых, когда происходит тайм-аут, когда приложение находится на переднем плане, я бы хотел, чтобы намерение сработало без какого-либо дальнейшего взаимодействия с пользователем. Вот где пригодится таймер (я сбрасываю его при изменении действий и onUserInteraction () — если он опустится до 0, он запустит намерение).

2. В любом случае, как вы предлагаете, я могу обновить значение учетных данных (например, timeOfLastAction ), чтобы отслеживать самые последние действия пользователя. Тем не менее, мне пришлось бы периодически проверять, действительны ли эти учетные данные (т. Е. Недостаточно старые для тайм-аута запуска), и показывать диалоговое окно, если они стали недействительными с момента последней проверки. Чтобы реализовать эту функциональность, мне пришлось бы сохранить таймер, верно?

3. @Jordan: Просто проверьте, исправны ли учетные данные в onResume() , поскольку вы уже обновляете свои timeOfLastAction там. Если вы действительно параноик, также проверьте учетные данные в таких местах, как onPrepareOptionsMenu() .

Ответ №2:

У вас может быть глобальная статическая переменная, чтобы проверить, находится ли приложение на переднем плане:

 public static boolean isForeground = false;
  

При каждой операции onPause устанавливайте переменную false
При каждом действии onResume устанавливайте переменную true

Таким образом, вы узнаете, находится ли приложение на переднем плане или нет.

По истечении времени ожидания, если действие находится на переднем плане, запустите намерение. Если это не так, установите глобальную статическую переменную true . Эта переменная будет проверяться при каждом onResume, и если она истинна, она активирует намерение тайм-аута (таким образом, она будет активирована при возобновлении работы приложения).

 public static boolean hasTimeout = false;
  

Это будет проще, если у вас есть BaseActivity, где вы это реализуете, который расширяется за счет всех других действий.

Комментарии:

1. Я собирался опубликовать почти то же самое, когда появился ваш ответ. Единственное отличие заключается в том, что я думал о флаге в SharedPreferences вместо статического поля.