comprobar la aplicación de Android está en primer plano o no?

Recibí muchas respuestas para esta pregunta. Pero se trata de una sola actividad … ¿Cómo comprobar si toda la aplicación se ejecuta en primer plano o no?

La respuesta de @ user370305 es propensa a errores y desalentada por los desarrolladores de SO Android (compruebe https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ )

Hay un enfoque mucho más simple:

En una actividad base que todas las actividades se extienden :

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

Siempre que necesite verificar si alguna de sus actividades de aplicación está en primer plano, simplemente marque isVisible();

Para comprender este enfoque, verifique esta respuesta del ciclo de vida de la actividad side-by-side : Actividad ciclo de vida lado a lado

La forma más sencilla y no obsoleta que he encontrado hasta ahora para hacer esto, es la siguiente:

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

Solo funciona con SDK 16+.

EDITAR :

Eliminé el siguiente código de la solución:

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

ya que eso hace que no se reciban las notificaciones si la pantalla está bloqueada. Eché un vistazo al marco y el propósito de esto no está del todo claro. Lo eliminaría Verificar el estado de la información del proceso sería suficiente 🙂

He intentado con el filtro del paquete desde el proceso en ejecución. pero eso es muy raro. En lugar de eso, he intentado con una nueva solución y esto funciona perfectamente. Lo he comprobado muchas veces y obtuve el resultado perfecto a través de este módulo.

 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) { } }); } 

verifica si la aplicación está en segundo plano o en primer plano. Este método devolverá verdadero si la aplicación está en segundo plano.

Primero agregue el permiso GET_TASKS a su 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 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 taskInfo = am.getRunningTasks(1); ComponentName componentInfo = taskInfo.get(0).topActivity; if (componentInfo.getPackageName().equals(context.getPackageName())) { isInBackground = false; } } return isInBackground; } 

Con las nuevas extensiones de Android Architecture of Lifecycle, podemos lograr esto con la mayor facilidad.

Solo asegúrese de obtener esta dependencia en su archivo build.gradle:

 dependencies { implementation "android.arch.lifecycle:extensions:1.1.0" } 

Luego, en su clase de Aplicación, use esto:

 class ArchLifecycleApp : Application(), LifecycleObserver { override fun onCreate() { super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(this) } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onAppBackgrounded() { Log.d("MyApp", "App in background") } @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onAppForegrounded() { Log.d("MyApp", "App in foreground") } } 

Al final, actualice su archivo AndroidManifest.xml con:

   

Ahora, cada vez que la Aplicación vaya a Primer plano o Fondo, recibiremos los Registros asociados con los dos métodos declarados.

Encontré una solución simple para esto al crear una clase de actividad base, debes extender todas tus clases de actividad desde aquí:

 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(); } } 

Clase 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; } 

No hay callback global para esto, pero para cada actividad es onStop (). No es necesario que te metas con una int atómica. Solo tiene un int global con la cantidad de actividades iniciadas, en cada actividad incremente en onStart () y disminuya en 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(); } } } 

La respuesta de cesards es correcta, pero solo para API> 15. Para versiones de API inferiores, decidí usar el método 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(); } } 

Por favor, avíseme si funciona para todos ustedes.

Pruebe ActivityLifecycleCallbacks en su clase de aplicación.

Ninguna de las soluciones basadas en getRunningTasks () funciona en versiones recientes de Android, getRunningTasks () se desaprobó en API nivel 21. Incluso si todavía se usa, no devuelve suficiente información para determinar si la aplicación está en primer plano.

En su lugar, amplíe la clase de aplicación y use Application.ActivityLifecycleCallbacks para rastrear el estado de visibilidad de la aplicación.

 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) { } }); } } 

El uso del temporizador de protección de 400 ms elimina la detección falsa del estado de fondo al cambiar de actividades en la misma aplicación. El estado de fondo / primer plano se puede consultar en cualquier momento usando:

 MyApplication.isForeground(); 

Una clase también puede escuchar los eventos de difusión si está interesado en las transiciones de estado:

 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); 

A continuación, se encuentra la solución actualizada para el último SDK de Android.

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

Espero que esto ayude, gracias.

A continuación, la solución funciona desde el nivel de API 14+

Backgrounding ComponentCallbacks2 – Ver la documentación no es 100% claro sobre cómo usaría esto. Sin embargo, eche un vistazo más de cerca y notará que el método onTrimMemory pasa en una bandera. Estos indicadores generalmente tienen que ver con la disponibilidad de la memoria, pero el que nos interesa es TRIM_MEMORY_UI_HIDDEN. Al verificar si la IU está oculta, podemos suponer que la aplicación está ahora en segundo plano. No es exactamente obvio, pero debería funcionar.

Foregrounding ActivityLifecycleCallbacks: podemos usar esto para detectar los conocimientos adquiridos anulando onActivityResumed y haciendo un seguimiento del estado actual de la aplicación (Foreground / Background).

Crea nuestra interfaz que será implementada por una clase de aplicación personalizada

 interface LifecycleDelegate { fun onAppBackgrounded() fun onAppForegrounded() } 

Cree una clase que vaya a implementar ActivityLifecycleCallbacks y ComponentCallbacks2 y anule los métodos ActivityResumed y onTrimMemory

 // Take an instance of our lifecycleHandler as a constructor parameter class AppLifecycleHandler(private val lifecycleDelegate: LifecycleDelegate) : Application.ActivityLifecycleCallbacks, ComponentCallbacks2 // <-- Implement these { private var appInForeground = false // Override from Application.ActivityLifecycleCallbacks override fun onActivityResumed(p0: Activity?) { if (!appInForeground) { appInForeground = true lifecycleDelegate.onAppForegrounded() } } // Override from ComponentCallbacks2 override fun onTrimMemory(level: Int) { if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // lifecycleDelegate instance was passed in on the constructor lifecycleDelegate.onAppBackgrounded() } } } 

Ahora todo lo que tenemos que hacer es que nuestra clase de aplicación personalizada implemente nuestra interfaz LifecycleDelegate y se registre.

 class App : Application(), LifeCycleDelegate { override fun onCreate() { super.onCreate() val lifeCycleHandler = AppLifecycleHandler(this) registerLifecycleHandler(lifeCycleHandler) } override fun onAppBackgrounded() { Log.d("Awww", "App in background") } override fun onAppForegrounded() { Log.d("Yeeey", "App in foreground") } private fun registerLifecycleHandler(lifeCycleHandler: AppLifecycleHandler) { registerActivityLifecycleCallbacks(lifeCycleHandler) registerComponentCallbacks(lifeCycleHandler) } } 

En Manifest establece la CustomApplicationClass

  

La biblioteca de Android Architecture Components puede usar ProcessLifecycleOwner para configurar un escucha para todo el proceso de aplicación para eventos onStart y onStop. Para hacer esto, haga que su clase de aplicación implemente la interfaz de LifecycleObserver y agregue algunas anotaciones para onStop y onStart a sus métodos de fondo y primer plano.

 class ArchLifecycleApp : Application(), LifecycleObserver { override fun onCreate() { super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(this) } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onAppBackgrounded() { Log.d("Awww", "App in background") } @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onAppForegrounded() { Log.d("Yeeey", "App in foreground") } } 

Desde Android 19, puede registrar una callback de ciclo de vida de la aplicación en onCreate () de su clase de aplicación de esta manera:

 @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new AppLifecycleCallback()); } 

El AppLifecycleCallback se ve así:

 class AppLifecycleCallback implements Application.ActivityLifecycleCallbacks { private int numStarted = 0; @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) { if (numStarted == 0) { //app went to foreground } numStarted++; } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { numStarted--; if (numStarted == 0) { // app went to background } } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }