НЕ ИСПОЛЬЗУЙТЕ ЭТО ОТВЕТ
user1269737 ответ является правильным (одобренным Google / Android) способом сделать это . Прочитайте их ответ и дайте им + 1.
Я оставлю свой оригинальный ответ здесь ради потомков. Это было лучшее из доступных в 2012 году, но теперь Android имеет соответствующую поддержку.
Оригинальный ответ
Ключ использует ActivityLifecycleCallbacks
(обратите внимание, что для этого требуется Android API уровня 14 (Android 4.0)). Просто проверьте, равно ли количество остановленных действий количеству запущенных действий. Если они равны, ваша заявка в фоновом режиме. Если есть еще запущенные действия, ваше приложение все еще отображается. Если действия возобновлены, а не приостановлены, приложение не только отображается, но и на переднем плане. Существуют 3 основных состояния, в которых ваша деятельность может находиться, затем: видимая и на переднем плане, видимая, но не на переднем плане, и не видимая и не на переднем плане (т.е. на заднем плане).
Действительно приятная вещь в этом методе состоит в том, что у него нет асинхронных проблем getRunningTasks()
, но вам также не нужно изменять каждый Activity
в вашем приложении для установки / сброса чего-либо в onResumed()
/ onPaused()
. Это всего лишь несколько строк кода, которые самодостаточны и работают во всем приложении. Плюс, никаких фанки-разрешений тоже не требуется.
MyLifecycleHandler.java:
public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
// I use four separate variables here. You can, of course, just use two and
// increment/decrement them instead of using four and incrementing them all.
private int resumed;
private int paused;
private int started;
private int stopped;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
++resumed;
}
@Override
public void onActivityPaused(Activity activity) {
++paused;
android.util.Log.w("test", "application is in foreground: " + (resumed > paused));
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityStarted(Activity activity) {
++started;
}
@Override
public void onActivityStopped(Activity activity) {
++stopped;
android.util.Log.w("test", "application is visible: " + (started > stopped));
}
// If you want a static function you can use to check if your application is
// foreground/background, you can use the following:
/*
// Replace the four variables above with these four
private static int resumed;
private static int paused;
private static int started;
private static int stopped;
// And these two public static functions
public static boolean isApplicationVisible() {
return started > stopped;
}
public static boolean isApplicationInForeground() {
return resumed > paused;
}
*/
}
MyApplication.java:
// Don't forget to add it to your manifest by doing
// <application android:name="your.package.MyApplication" ...
public class MyApplication extends Application {
@Override
public void onCreate() {
// Simply add the handler, and that's it! No need to add any code
// to every activity. Everything is contained in MyLifecycleHandler
// with just a few lines of code. Now *that's* nice.
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
}
}
@ Mewzer задал несколько хороших вопросов об этом методе, на которые я хотел бы ответить в этом ответе для всех:
onStop()
не вызывается в ситуациях нехватки памяти; это проблема здесь?
Нет. Документы для onStop()
говорят:
Обратите внимание, что этот метод никогда не может быть вызван в ситуациях нехватки памяти, когда системе не хватает памяти для поддержания процесса вашей активности после вызова метода onPause ().
Ключевым моментом здесь является то, чтобы «поддерживать процесс вашей активности в рабочем состоянии ...». Если эта ситуация с нехваткой памяти когда-либо будет достигнута, ваш процесс фактически будет уничтожен (а не только ваша деятельность). Это означает, что этот метод проверки на фоновую целостность все еще действителен, потому что а) вы все равно не можете проверить фоновую обработку, если ваш процесс убит, и б) если ваш процесс запускается снова (потому что создается новое действие), член переменные (статические или нет) для MyLifecycleHandler
будут сброшены на 0
.
Это работает для изменений конфигурации?
По умолчанию нет. Вы должны явно установить configChanges=orientation|screensize
(|
с чем угодно) в файле манифеста и обработать изменения конфигурации, иначе ваша деятельность будет уничтожена и воссоздана. Если вы не установите это, методы вашей деятельности будут вызываться в следующем порядке: onCreate -> onStart -> onResume -> (now rotate) -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume
. Как видите, перекрытия нет (как правило, при переключении между двумя действиями очень кратко перекрываются два действия, как работает этот метод обнаружения фона). Чтобы обойти это, вы должны установить configChanges
, чтобы ваша деятельность не была разрушена. К счастью, мне пришлось установить configChanges
уже во всех моих проектах, потому что было нежелательно, чтобы вся моя деятельность разрушалась при повороте / изменении размера экрана, поэтому я никогда не считал это проблематичным. (спасибо dpimka за то, что освежил мою память об этом и исправил меня!)
Одна нота:
Когда я сказал «фон» в этом ответе, я имел в виду «ваше приложение больше не видно». Действия Android могут быть видны, но не на переднем плане (например, если есть прозрачное наложение уведомлений). Вот почему я обновил этот ответ, чтобы отразить это.
Важно знать, что у Android есть странный неопределенный момент при переключении действий, когда ничего не находится на переднем плане .По этой причине, если вы проверяете, находится ли ваше приложение на переднем плане при переключении между действиями (в том же приложении), вам будет сказано, что вы не на переднем плане (даже если ваше приложение все еще является активным приложением и отображается).
Вы можете проверить, находится ли ваше приложение на переднем плане в вашем Activity
onPause()
методе после super.onPause()
.Просто запомните странное состояние неопределенности, о котором я только что говорил.
Вы можете проверить, является ли ваше приложение видимым (то есть, если оно не на заднем плане) в вашем Activity
onStop()
методе после super.onStop()
.