Android: How to detect when App goes background/foreground

It’s very easy to detect when an Activity goes background/foreground just by listening to the lifecycle events, onStop() and onStart() of that Activity. But, there are no straightforward lifecycle methods to tell you when the whole Application goes background/foreground.

With the latest Architecture components, it is easy to detect this and you can read more about this in here. https://proandroiddev.com/react-to-app-foreground-and-background-events-with-processlifecycleowner-96278e5816fa

However, in this article, I’m going to detect it without using the Architecture Components. Actually, more or less, the Architecture Components internally uses similar approach to detect when the App goes background/foreground. So, knowing this will help you have a better understanding when you use the Architecture Components to achieve this.

With a little workaround, it is possible. Here, ActivityLifecycleCallbacks comes to the rescue. Let me walkthrough step-by-step.

First, create a class that extends the android.app.Application and implements the ActivityLifecycleCallbacks interface. In the Application.onCreate(), register the callback.

public class App extends Application implements ActivityLifecycleCallbacks
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}

Register the “App” class in the Manifest as below,

<application
android:name=".App"

This is how the ActivityLifecycleCallbacks interface looks like,

public interface ActivityLifecycleCallbacks {
void onActivityCreated(Activity activity, Bundle savedInstanceState);
void onActivityStarted(Activity activity);
void onActivityResumed(Activity activity);
void onActivityPaused(Activity activity);
void onActivityStopped(Activity activity);
void onActivitySaveInstanceState(Activity activity, Bundle outState);
void onActivityDestroyed(Activity activity);
}

So, when any of your Activity(Activities you created or included by your Libraries) goes through any of the above mentioned lifecycle methods, these callbacks will be called.

There will be at least one Activity in the started state when the app is in the foreground and there will be no Activity in the started state when the app is in the background.

Declare 2 variables as below in the “App” class.

private int activityReferences = 0;
private boolean isActivityChangingConfigurations = false;

activityReferences will keep the count of number of Activities in the started state. isActivityChangingConfigurations is a flag to indicate if the current Activity is going through configuration change like orientation switch.

Using the following code you can detect if the App comes foreground.

@Override
public void onActivityStarted(Activity activity) {
if (++activityReferences == 1 && !isActivityChangingConfigurations) {
// App enters foreground
}
}

This is how to detect if the App goes background.

Override
public void onActivityStopped(Activity activity) {

isActivityChangingConfigurations = activity.isChangingConfigurations();
if (--activityReferences == 0 && !isActivityChangingConfigurations) {
// App enters background
}
}

How it works:

This is a little trick done with the way the Lifecycle methods are called in sequence. Let me walkthrough a scenario.

Assume that the user launches the App and the Launcher Activity A is launched. The Lifecycle calls will be,

  • A.onCreate()
  • A.onStart() (++activityReferences == 1) (App enters Foreground)
  • A.onResume()

The Activity A starts Activity B.

  • A.onPause()
  • B.onCreate()
  • B.onStart() (++activityReferences == 2)
  • B.onResume()
  • A.onStop() (--activityReferences == 1)

Then the user navigates back from Activity B,

  • B.onPause()
  • A.onStart() (++activityReferences == 2)
  • A.onResume()
  • B.onStop() (--activityReferences == 1)
  • B.onDestroy()

Then the user presses Home button,

  • A.onPause()
  • A.onStop() (--activityReferences == 0) (App enters Background)

In case, if the user presses Home button from Activity B instead of Back button, still it will be the same and activityReferences will be 0. Hence, we can detect as the App entering Background.

So, what’s the role of isActivityChangingConfigurations? In the above scenario, suppose the Activity B changes the orientation. The callback sequqnce will be,

  • B.onPause()
  • B.onStop() (--activityReferences == 0) (App enters Background??)
  • B.onDestroy()
  • B.onCreate()
  • B.onStart() (++activityReferences == 1) (App enters Foreground??)
  • B.onResume()

That’s why we have an additional check of isActivityChangingConfigurations to avoid the scenario when the Activity is going through the Configuration changes.


However, please note that this way of detecting will work only for the Activities you own (Either you created or included by your Libraries). If you start an Activity of any other App, it will still be considered as your App is in Background.


This solution I eloborated in here was originally from an old StackOverflow answer. But, I couldn’t find it out now to share here. Thanks to that random fellow Android developer.