Проверить приложение Android на переднем плане или нет?

Я рассмотрел множество ответов на этот вопрос. Но все дело в единичной активности. Как проверить, работает ли все приложение на переднем плане или нет?

Solutions Collecting From Web of "Проверить приложение Android на переднем плане или нет?"

Я не понимаю, чего вы хотите, но вы можете обнаружить в настоящее время приложение foreground / background с вызовом ActivityManager.getRunningAppProcesses() .

Что-то вроде,

 class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> { @Override protected Boolean doInBackground(Context... params) { final Context context = params[0].getApplicationContext(); return isAppOnForeground(context); } private boolean isAppOnForeground(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); if (appProcesses == null) { return false; } final String packageName = context.getPackageName(); for (RunningAppProcessInfo appProcess : appProcesses) { if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) { return true; } } return false; } } // Use like this: boolean foregroud = new ForegroundCheckTask().execute(context).get(); 

Также дайте мне знать, если я неправильно понимаю ..

ОБНОВЛЕНИЕ. Посмотрите на этот вопрос SO. Определение текущего приложения переднего плана из фоновой задачи или службы приведет к дополнительной информации ..

Благодаря..

Ответ @ user370305 является склонным к ошибкам и обескуражен разработчиками ОС Android (проверьте https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ )

Существует гораздо более простой подход:

В BaseActivity все действия расширяются :

 protected static boolean isVisible = false; @Override public void onResume() { super.onResume(); setVisible(true); } @Override public void onPause() { super.onPause(); setVisible(false); } 

Всякий раз, когда вам нужно проверить, находится ли какая-либо из ваших приложений на переднем плане, просто проверьте isVisible();

Чтобы понять этот подход, проверьте этот ответ о жизненном цикле деятельности «бок о бок» : жизненный цикл активности бок о бок

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

 private int numRunningActivities = 0; public void onCreate() { super.onCreate(); this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityStarted(Activity activity) { numRunningActivities++; if (numRunningActivities == 1) { LogUtils.d("APPLICATION", "APP IN FOREGROUND"); } } @Override public void onActivityStopped(Activity activity) { numRunningActivities--; if (numRunningActivities == 0) { Log.e("", "App is in BACKGROUND") } } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityDestroyed(Activity activity) { } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } }); } 

Самый аккуратный и не устаревший способ, который я нашел до сих пор, заключается в следующем:

 @Override public boolean foregrounded() { ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo(); ActivityManager.getMyMemoryState(appProcessInfo); return (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE) } 

Он работает только с SDK 16+.

EDIT :

Я удалил из этого кода следующий код:

 KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); // App is foreground, but screen is locked, so show notification return km.inKeyguardRestrictedInputMode(); 

Поскольку это не делает уведомления, если экран заблокирован. Я взглянул на рамки, и цель этого не совсем ясна. Я бы убрал его. Проверка состояния информации о состоянии будет достаточно 🙂

Проверьте, находится ли приложение в фоновом режиме или на переднем плане. Этот метод вернет true, если приложение находится в фоновом режиме.

Сначала добавьте разрешение GET_TASKS на ваш AndroidManifest.xml

 private boolean isAppIsInBackground(Context context) { boolean isInBackground = true; ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) { List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { for (String activeProcess : processInfo.pkgList) { if (activeProcess.equals(context.getPackageName())) { isInBackground = false; } } } } } else { List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); ComponentName componentInfo = taskInfo.get(0).topActivity; if (componentInfo.getPackageName().equals(context.getPackageName())) { isInBackground = false; } } return isInBackground; } 

Я нашел для вас простое решение, создав базовый класс активности, и должен расширять все ваши классы активности из этого:

 public class BaseActivity extends ActionBarActivity { @Override protected void onResume() { ApplicationStateChecker.view_resumed(this); super.onResume(); } @Override protected void onStop() { ApplicationStateChecker.view_stopped(this); super.onStop(); } @Override protected void onPause() { ApplicationStateChecker.view_paused(this); super.onPause(); } } 

Класс ApplicationStateChecker:

 public class ApplicationStateChecker { private static final String _pause_string = "paused"; private static final String _resume_string = "resumed"; private static String _view_lastState; private static boolean _from_background = true; public static void view_paused(Activity activity){ _view_lastState = _pause_string; } public static void view_stopped(Activity activity){ if ( _view_lastState.equals(_pause_string) ){ //if stop called and last event was pause then app is brought to background _from_background = true; } //if } public static void view_resumed(Activity activity){ if ( _from_background ) { //Do your stuff here , app is brought to foreground } //if _from_background = false; _view_lastState = _resume_string; } 

Глобального обратного вызова для этого нет, но для каждого действия это onStop (). Вам не нужно связываться с атомарным int. Просто используйте глобальный int с количеством запущенных действий, в каждом действии увеличивайте его в onStart () и уменьшите его на onStop ().

 public class BaseActivity extends ActionBarActivity { public static int count = 0; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onStart() { super.onStart(); count = count + 1; Log.d(TAG, "onStart" + count); if (count == 1) { Toast.makeText(getApplicationContext(), "online", Toast.LENGTH_SHORT).show(); } } protected void onStop() { super.onStop(); count = count - 1; if (count == 0) { Toast.makeText(getApplicationContext(), "offline", Toast.LENGTH_SHORT).show(); } } } 

Ответ cesars верен, но только для API> 15. Для более низких версий API я решил использовать getRunningTasks() :

  private boolean isAppInForeground(Context context) { if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0); String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName(); return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase()); } else { ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo(); ActivityManager.getMyMemoryState(appProcessInfo); if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE) { return true; } KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); // App is foreground, but screen is locked, so show notification return km.inKeyguardRestrictedInputMode(); } } 

Пожалуйста, дайте мне знать, работает ли это для вас всех.

Попробуйте ActivityLifecycleCallbacks в вашем классе Application.

Ни одно из решений, основанных на getRunningTasks (), не работает в последних версиях Android, getRunningTasks () устарел на уровне API 21. Даже если он все еще используется, он не возвращает достаточную информацию, чтобы определить, находится ли приложение на переднем плане.

Вместо этого расширьте класс Application и используйте Application.ActivityLifecycleCallbacks для отслеживания состояния видимости приложения.

 public class MyApplication extends Application { static final String APP_STATE_FOREGROUND = "com.xxx.appstate.FOREGROUND"; static final String APP_STATE_BACKGROUND = "com.xxx.appstate.BACKGROUND"; private static int m_foreground = -1; private Handler m_handler = new Handler(); private Runnable m_guard; public static boolean isForeground() { return m_foreground == 1; } @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle bundle) { } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { if(m_guard != null) { m_handler.removeCallbacks(m_guard); m_guard = null; } if(m_foreground == 1) return; m_foreground = 1; sendBroadcast(new Intent(APP_STATE_FOREGROUND)); } @Override public void onActivityPaused(Activity activity) { if(m_foreground == 0) return; /* * Use a 400ms guard to protect against jitter * when switching between two activities * in the same app */ m_guard = new Runnable() { @Override public void run() { if(m_foreground == 1) { m_foreground = 0; sendBroadcast(new Intent(APP_STATE_BACKGROUND)); } } }; m_handler.postDelayed(m_guard, 400); } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { } @Override public void onActivityDestroyed(Activity activity) { } }); } } 

Использование таймера защиты 400 мс устраняет ложное обнаружение состояния фона при переключении между действиями в одном приложении. Состояние фона / переднего плана можно запросить в любое время, используя:

 MyApplication.isForeground(); 

Класс также может прослушивать события трансляции, если он заинтересован в переходах состояния:

 private static IntentFilter m_appStateFilter; static { m_appStateFilter = new IntentFilter(); m_appStateFilter.addAction(MyApplication.APP_STATE_FOREGROUND); m_appStateFilter.addAction(MyApplication.APP_STATE_BACKGROUND); } private BroadcastReceiver m_appStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(MyApplication.APP_STATE_FOREGROUND)) { /* application entered foreground */ } else if (action.equals(MyApplication.APP_STATE_BACKGROUND)) { /* application entered background */ } } }; registerReceiver(m_appStateReceiver, m_appStateFilter); 

Ниже приведено новое решение для Android Android SDK.

 String PackageName = context.getPackageName(); ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); ComponentName componentInfo; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { List<ActivityManager.AppTask> tasks = manager.getAppTasks(); componentInfo = tasks.get(0).getTaskInfo().topActivity; } else { List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1); componentInfo = tasks.get(0).topActivity; } if (componentInfo.getPackageName().equals(PackageName)) return true; return false; 

Надеюсь, это поможет, спасибо.