check android application is in foreground or not?

Android

Android Problem Overview


I went through a lot of answers for this question.But it's all about single activity..How to check whether the whole app is running in foreground or not ?

Android Solutions


Solution 1 - Android

I don't understand what you want, but You can detect currently foreground/background application with ActivityManager.getRunningAppProcesses() call.

Something like,

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

Also let me know if I misunderstand..

UPDATE: Look at this SO question Determining the current foreground application from a background task or service fore more information..

Thanks..

Solution 2 - Android

Update Oct 2020: Checkout the Lifecycle extensions based solutions on this thread. The approach seems to be working, it's more elegant and modern.


The neatest and not deprecated way that I've found so far to do this, as follows:

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

It only works with SDK 16+.

EDIT:

I removed the following code from the solution:

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

since that makes not getting the notifications if the screen locked. I had a look to the framework and the purpose of this is not entirely clear. I'd remove it. Checking the process info state would be enough :-)

Solution 3 - Android

@user370305's answer is error prone and discouraged by Android OS Developers (check https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ)

There is a much more simpler approach:

On a BaseActivity that all Activities extend:

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

@Override
public void onPause() {
    super.onPause();
    setVisible(false);
}

Whenever you need to check if any of your application activities is in foreground just check isVisible();

To understand this approach check this answer of side-by-side activity lifecycle: https://stackoverflow.com/questions/10094131/what-is-exactly-the-android-activity-flow/10094227#10094227

Solution 4 - Android

With the new Android Architecture of Lifecycle extensions, we can achieve this with utmost ease.

Just ensure you pull this dependency in your build.gradle file:

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

Then in your Application class, use this:

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

In the end, update your AndroidManifest.xml file with:

<application
    android:name=".ArchLifecycleApp"
    //Your extra code
    ....>
</application>

Now, on everytime the Application goes to Foreground or Background, we are going to receive the Logs associated with the two methods declared.

Solution 5 - Android

Android Architecture Components library you can use the ProcessLifecycleOwner to set up a listener to the whole application process for onStart and onStop events. To do this, make your application class implement the LifecycleObserver interface and add some annotations for onStart and onStop to your foreground and background methods.

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

}

Solution 6 - Android

I have tried with package filter from running process. but that is very weird. Instead of that, I have try new solution and this work perfectly. I have checked many times and getting perfect result through this 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) {
                }
            });
}

Solution 7 - Android

check if the app is in background or foreground. This method will return true if the app is in background.

First add the GET_TASKS permission to your 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;
}

Solution 8 - Android

I've found a simple soluition for this by creating a base activity class , u must extend all your activity classes from this :

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 class :

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

Solution 9 - Android

There is no global callback for this, but for each activity it is onStop(). You don't need to mess with an atomic int. Just have a global int with the number of started activities, in every activity increment it in onStart() and decrement it in 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();

    }
}


}

Solution 10 - Android

cesards's answer is correct, but only for API > 15. For lower API versions I decided to use getRunningTasks() method:

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

Please, let me know if it works for you all.

Solution 11 - Android

None of the solutions base on getRunningTasks() works in recent Android versions, getRunningTasks() was deprecated in API level 21. Even if it is still used it does not return enough information to determine if the app is in the foreground.

Instead extend the Application class and use Application.ActivityLifecycleCallbacks to track application visibility state.

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

Using the 400ms guard timer eliminates false detection of background state when switching between activities in the same app. The background/foreground state can be queried at anytime using:

MyApplication.isForeground();

A class can also listen for the broadcast events if it is interested in the state transitions:

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

Solution 12 - Android

Try ActivityLifecycleCallbacks in your Application class.

Solution 13 - Android

Below is updated solution for the latest 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;

Hope this helps, thanks.

Solution 14 - Android

Below solution works from API level 14+

Backgrounding ComponentCallbacks2 — Looking at the documentation is not 100% clear on how you would use this. However, take a closer look and you will noticed the onTrimMemory method passes in a flag. These flags are typically to do with the memory availability but the one we care about is TRIM_MEMORY_UI_HIDDEN. By checking if the UI is hidden we can potentially make an assumption that the app is now in the background. Not exactly obvious but it should work.

Foregrounding ActivityLifecycleCallbacks — We can use this to detect foreground by overriding onActivityResumed and keeping track of the current application state (Foreground/Background).

Create our interface that will be implemented by a custom Application class

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

Create a class that is going to implement the ActivityLifecycleCallbacks and ComponentCallbacks2 and override onActivityResumed and onTrimMemory methods

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

Now all we need to do is have our custom Application class implement our LifecycleDelegate interface and register.

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

}

In Manifest set the CustomApplicationClass

<application
        android:name=".App"

Solution 15 - Android

From Android 19, you can register an app life cycle callback in your Application class's onCreate() like this:

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

The AppLifecycleCallback looks like this:

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

    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhackerView Question on Stackoverflow
Solution 1 - Androiduser370305View Answer on Stackoverflow
Solution 2 - AndroidcesardsView Answer on Stackoverflow
Solution 3 - AndroidneteinsteinView Answer on Stackoverflow
Solution 4 - AndroidmhtmalpaniView Answer on Stackoverflow
Solution 5 - AndroidRockyView Answer on Stackoverflow
Solution 6 - AndroidJitendra ramoliyaView Answer on Stackoverflow
Solution 7 - AndroidS.Sathya PriyaView Answer on Stackoverflow
Solution 8 - AndroidVlad SudakovView Answer on Stackoverflow
Solution 9 - AndroidKishan VaghelaView Answer on Stackoverflow
Solution 10 - AndroidAyaz AlifovView Answer on Stackoverflow
Solution 11 - AndroidBitByteDogView Answer on Stackoverflow
Solution 12 - Androiduser5330674View Answer on Stackoverflow
Solution 13 - AndroidKrzysztof HuminskiView Answer on Stackoverflow
Solution 14 - AndroidRockyView Answer on Stackoverflow
Solution 15 - AndroidZiwei ZengView Answer on Stackoverflow