vérifier l’application Android est au premier plan ou non?

Je suis passé par beaucoup de réponses à cette question.Mais c’est une question d’activité unique..Comment vérifier si l’application entière est en cours d’exécution au premier plan ou non?

Je ne comprends pas ce que vous voulez, mais vous pouvez détecter l’application de premier plan / d’arrière-plan avec l’appel ActivityManager.getRunningAppProcesses() .

Quelque chose comme,

 class ForegroundCheckTask extends AsyncTask { @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 appProcesses = activityManager.getRunningAppProcesses(); if (appProcesses == null) { return false; } final Ssortingng 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(); 

Dites-moi aussi si je comprends mal ..

MISE À JOUR: Regardez cette question SO Déterminer l’application actuelle au premier plan à partir d’une tâche ou d’un service d’ arrière-plan pour plus d’informations.

Merci..

La réponse de @ user370305 est sujette aux erreurs et découragée par les développeurs de systèmes d’exploitation Android (consultez https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ )

Il y a une approche beaucoup plus simple:

Sur une BaseActivity étendue à toutes les activités :

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

Chaque fois que vous devez vérifier si l’une de vos activités d’application est au premier plan, cochez simplement la isVisible();

Pour comprendre cette approche, consultez la réponse du cycle de vie des activités côte à côte : Cycle de vie des activités côte à côte

La manière la plus simple et la moins obsolète que j’ai trouvée jusqu’ici pour ce faire est la suivante:

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

Il ne fonctionne qu’avec le SDK 16+.

EDIT :

J’ai supprimé le code suivant de la solution:

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

puisque cela ne permet pas de recevoir les notifications si l’écran est verrouillé. J’ai jeté un coup d’oeil au cadre et l’objective de ce n’est pas tout à fait clair. Je le retirerais Vérifier l’état des informations sur le processus serait suffisant 🙂

J’ai essayé avec le filtre de paquet du processus en cours d’exécution. mais c’est très bizarre. Au lieu de cela, j’ai essayé de nouvelles solutions et cela fonctionne parfaitement. J’ai vérifié plusieurs fois et obtenu un résultat parfait grâce à ce module.

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

vérifiez si l’application est en arrière-plan ou au premier plan. Cette méthode retournera true si l’application est en arrière-plan.

Ajoutez d’abord l’autorisation GET_TASKS à votre 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 (Ssortingng 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; } 

Avec la nouvelle architecture des extensions du cycle de vie Android, nous pouvons y parvenir avec la plus grande facilité.

Assurez-vous simplement de tirer cette dépendance dans votre fichier build.gradle:

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

Ensuite, dans votre classe d’application, utilisez ceci:

 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") } } 

Au final, mettez à jour votre fichier AndroidManifest.xml avec:

   

Maintenant, à chaque fois que l’application passe au premier plan ou en arrière-plan, nous allons recevoir les journaux associés aux deux méthodes déclarées.

J’ai trouvé une solution simple à cela en créant une classe d’activités de base.

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

Classe ApplicationStateChecker:

 public class ApplicationStateChecker { private static final Ssortingng _pause_ssortingng = "paused"; private static final Ssortingng _resume_ssortingng = "resumed"; private static Ssortingng _view_lastState; private static boolean _from_background = true; public static void view_paused(Activity activity){ _view_lastState = _pause_ssortingng; } public static void view_stopped(Activity activity){ if ( _view_lastState.equals(_pause_ssortingng) ){ //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_ssortingng; } 

Il n’y a pas de rappel global pour cela, mais pour chaque activité, il s’agit de onStop (). Vous n’avez pas besoin de jouer avec un int atomique. Il suffit d’avoir un int global avec le nombre d’activités démarrées, dans chaque activité, incrémentez-le dans onStart () et décrémentez-le dans 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 réponse de cesards est correcte, mais uniquement pour les API> 15. Pour les versions d’API inférieures, j’ai décidé d’utiliser la méthode 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(); } } 

S'il vous plaît, faites-moi savoir si cela fonctionne pour vous tous.

Essayez ActivityLifecycleCallbacks dans votre classe d’application.

Aucune base de solutions sur getRunningTasks () ne fonctionne dans les versions récentes d’Android, getRunningTasks () est obsolète au niveau 21 de l’API. Même si elle est toujours utilisée, elle ne renvoie pas suffisamment d’informations pour déterminer si l’application est au premier plan.

Au lieu de cela, étendez la classe Application et utilisez Application.ActivityLifecycleCallbacks pour suivre l’état de visibilité de l’application.

 public class MyApplication extends Application { static final Ssortingng APP_STATE_FOREGROUND = "com.xxx.appstate.FOREGROUND"; static final Ssortingng 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) { } }); } } 

L’utilisation de la timer de protection 400ms élimine la détection erronée de l’état d’arrière-plan lors du passage d’une activité à une autre dans la même application. L’état d’arrière-plan / avant-plan peut être interrogé à tout moment en utilisant:

 MyApplication.isForeground(); 

Une classe peut également écouter les événements de diffusion si elle est intéressée par les transitions d’état:

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

Vous trouverez ci-dessous une solution mise à jour pour le dernier SDK Android.

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

J’espère que ça aide, merci.

La solution ci-dessous fonctionne à partir du niveau API 14+

Backgrounding ComponentCallbacks2 – Il n’est pas clair à 100% de savoir comment utiliser ceci. Cependant, regardez de plus près et vous remarquerez que la méthode onTrimMemory passe dans un drapeau. Ces indicateurs sont généralement liés à la disponibilité de la mémoire, mais TRIM_MEMORY_UI_HIDDEN est notre priorité. En vérifiant si l’interface utilisateur est masquée, nous pouvons éventuellement supposer que l’application est maintenant en arrière-plan. Pas tout à fait évident mais ça devrait marcher.

Mise à jour de ActivityLifecycleCallbacks – Nous pouvons l’utiliser pour détecter le premier plan en remplaçant onActivityResumed et en conservant l’état actuel de l’application (Foreground / Background).

Créer notre interface qui sera implémentée par une classe d’application personnalisée

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

Créez une classe qui va implémenter ActivityLifecycleCallbacks et ComponentCallbacks2 et remplacez les méthodes onActivityResumed et 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() } } } 

Maintenant, tout ce que nous avons à faire est de faire en sorte que notre classe d'application personnalisée implémente notre interface LifecycleDelegate et s'enregistre.

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

Dans le manifeste, définissez le CustomApplicationClass

  

Bibliothèque de composants d’architecture Android Vous pouvez utiliser ProcessLifecycleOwner pour configurer un écouteur pour l’ensemble du processus d’application pour les événements onStart et onStop. Pour ce faire, faites en sorte que votre classe d’application implémente l’interface LifecycleObserver et ajoute des annotations pour onStop et onStart à vos méthodes de premier plan et d’arrière-plan.

 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") } } 

À partir d’Android 19, vous pouvez enregistrer un rappel de cycle de vie d’application dans le fichier onCreate () de votre classe d’application, comme ceci:

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

Le AppLifecycleCallback ressemble à ceci:

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