How to check if activity is in foreground or in visible background?

AndroidAndroid ActivityDialogActivity Finish

Android Problem Overview


I have a splash screen on a timer. My problem is that before I finish() my activity I need to check that the next activity has started because a system dialogue box pops-up and I only want to finish(); once the user has selected an option from the dialogue box?

I know that there are many questions on how to see if your activity is in the foreground but I do not know if this allows for dialogue boxes on top of the activity too.

Here is the problem, the red is my activity which is in the background while the dialogue is in the foreground:

the red is my activity which is in the background while the dialogue is in the foreground

EDIT: I have tried just not using finish() but then my activity can be gone back to in the stack of applications which I am trying to avoid.

Android Solutions


Solution 1 - Android

This is what is recommended as the right solution:

> The right solution (credits go to Dan, CommonsWare and NeTeInStEiN) > Track visibility of your application by yourself using > Activity.onPause, Activity.onResume methods. Store "visibility" status > in some other class. Good choices are your own implementation of the > Application or a Service (there are also a few variations of this > solution if you'd like to check activity visibility from the service). > > Example > Implement custom Application class (note the isActivityVisible() static method):

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

> Register your application class in AndroidManifest.xml:

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

> Add onPause and onResume to every Activity in the project (you may > create a common ancestor for your Activities if you'd like to, but if > your activity is already extended from MapActivity/ListActivity etc. > you still need to write the following by hand):

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

In your finish() method, you want to use isActivityVisible() to check if the activity is visible or not. There you can also check if the user has selected an option or not. Continue when both conditions are met.

The source also mentions two wrong solutions...so avoid doing that.

Source: stackoverflow

Solution 2 - Android

If targeting API level 14 or above, one can use android.app.Application.ActivityLifecycleCallbacks

public class MyApplication extends Application implements ActivityLifecycleCallbacks {
    private static boolean isInterestingActivityVisible;

    @Override
    public void onCreate() {
	    super.onCreate();
	
	    // Register to be notified of activity state changes
	    registerActivityLifecycleCallbacks(this);
        ....
    }

    public boolean isInterestingActivityVisible() {
        return isInterestingActivityVisible;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = true;
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = false;
        }
    }

    // Other state change callback stubs
    ....
}

Solution 3 - Android

UPD: updated to state Lifecycle.State.RESUMED. Thanks to @htafoya for that.

In 2019 with help of new support library 28+ or AndroidX you can simply use:

val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)

You can read more in the documenation to understand what happened under the hood.

Solution 4 - Android

Activity::hasWindowFocus() returns you the boolean you need.

public class ActivityForegroundChecker extends TimerTask
{
    private static final long FOREGROUND_CHECK_PERIOD = 5000;
    private static final long FIRST_DELAY             = 3000;

    private Activity m_activity;
    private Timer    m_timer;

    public ActivityForegroundChecker (Activity p_activity)
    {
        m_activity = p_activity;
    }

    @Override
    public void run()
    {
        if (m_activity.hasWindowFocus() == true) {
            // Activity is on foreground
            return;
        }
        // Activity is on background.
    }

    public void start ()
    {
        if (m_timer != null) {
            return;
        }
        m_timer = new Timer();
        m_timer.schedule(this, FIRST_DELAY, FOREGROUND_CHECK_PERIOD);
    }

    public void stop ()
    {
        if (m_timer == null) {
            return;
        }
        m_timer.cancel();
        m_timer.purge();
        m_timer = null;
    }
}

Here is an example class to check your activites' visibility from wherever you are.

Remember that if you show a dialog, the result will be false since the dialog will have the main focus. Other than that it's really handy and more reliable than suggested solutions.

Solution 5 - Android

That's exactly the difference between onPause and onStop events of the activity as described in the Activity class documentation.

If I understand you correctly, what you want to do is call finish() from your activity onStop to terminate it. See the attached image of the Activity Lifecycle Demo App. This is how it looks like when Activity B is launched from Activity A. The order of events is from bottom to top so you can see that Activity A onStop is called after Activity B onResume was already called.

Activity lifecycle demo

In case a dialog is shown your activity is dimmed in the background and only onPause is called.

Solution 6 - Android

Two possible solutions :

  1. Activity LifeCycle Callbacks

Use an Application that implements ActivityLifecycleCallbacks and use it to track Activities lifecycle events in you application. Note that ActivityLifecycleCallbacks are for Android api >= 14. For previous Android api, you'll need to implement it by yourself inside all of your activities ;-)

Use Application when you need to share / store states accross activities.

  1. Check for running process informations

You can check the status of a running process with this class RunningAppProcessInfo

Fetch the running process list with ActivityManager.getRunningAppProcesses() and filter the result list to check for the desired RunningAppProcessInfo and check its "importance"

Solution 7 - Android

I have create project on github app-foreground-background-listen

which uses very simple logic and works fine with all android API level.

Solution 8 - Android

Use the time gap between pause and resume from background to determine whether it is awake from background

In Custom Application

private static boolean isInBackground;
private static boolean isAwakeFromBackground;
private static final int backgroundAllowance = 10000;

public static void activityPaused() {
	isInBackground = true;
	final Handler handler = new Handler();
	handler.postDelayed(new Runnable() {
		@Override
		public void run() {
			if (isInBackground) {
				isAwakeFromBackground = true;
			}
		}
	}, backgroundAllowance);
	Log.v("activity status", "activityPaused");
}

public static void activityResumed() {
	isInBackground = false;
	if(isAwakeFromBackground){
		// do something when awake from background
		Log.v("activity status", "isAwakeFromBackground");
	}
	isAwakeFromBackground = false;
	Log.v("activity status", "activityResumed");
}

In BaseActivity Class

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

Solution 9 - Android

I think I have better solution. Because you can build in simply MyApplication.activityResumed(); to every Activity by one extend.

Firstly you have to create (like CyberneticTwerkGuruOrc)

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Next, you have to add Application class to AndroidManifest.xml

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Then, create class ActivityBase

public class ActivityBase extends Activity {

    @Override
    protected void onPause() {
        super.onPause();
        MyApplication.activityPaused();
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyApplication.activityResumed();
    }
}

Finally, when you crate new Activity, you can simply extends it by ActivityBase instead of Activity.

public class Main extends ActivityBase {
    @Override
    protected void onResume() {
        super.onResume();
    }
    
    @Override
    protected void onPause() {
        super.onPause();
    }
}

For me It's better method cause you have to just remember about extend by ActivityBase. In addition you can expand your base function in future. In my case I added receivers for my service and alerts about network in one class.

If you wanna check visibility of your App, you can simply call

MyApplication.isActivityVisible()

Solution 10 - Android

This can achieve this by a efficient way by using Application.ActivityLifecycleCallbacks

For example lets take Activity class name as ProfileActivity lets find whether its is in foreground or background

first we need to create our application class by extending Application Class

which implements

> Application.ActivityLifecycleCallbacks

Lets be my Application class as follows

Application class

public class AppController extends Application implements Application.ActivityLifecycleCallbacks {


private boolean activityInForeground;

@Override
public void onCreate() {
    super.onCreate();

//register ActivityLifecycleCallbacks  

    registerActivityLifecycleCallbacks(this);
   
}



public static boolean isActivityVisible() {
    return activityVisible;
}

public static void activityResumed() {
    activityVisible = true;
}

public static void activityPaused() {
    activityVisible = false;
}

private static boolean activityVisible;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {

}

public boolean isActivityInForeground() {
    return activityInForeground;
}
}

in the above class there is a override methord onActivityResumed of ActivityLifecycleCallbacks

 @Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

where all activity instance which is currently displayed on screen can be found, just check whether Your Activity is on Screen or not by the above method.

Register your Application class in manifest.xml

<application
    android:name=".AppController" />

To check weather Activity is Foreground or background as per the above solution call the following method on places you need to check

AppController applicationControl = (AppController) getApplicationContext();
    if(applicationControl.isActivityInForeground()){
     Log.d("TAG","Activity is in foreground")
    }
    else
    {
      Log.d("TAG","Activity is in background")
    }

Solution 11 - Android

If you want to know if any activity of your app is visible on the screen, you can do something like this:

public class MyAppActivityCallbacks implements Application.ActivityLifecycleCallbacks {
private Set<Class<Activity>> visibleActivities = new HashSet<>();

@Override
public void onActivityResumed(Activity activity) {
    visibleActivities.add((Class<Activity>) activity.getClass());
}

@Override
public void onActivityStopped(Activity activity) {
     visibleActivities.remove(activity.getClass());
}

public boolean isAnyActivityVisible() {
    return !visibleActivities.isEmpty();
}

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityStarted(Activity activity) {}

@Override
public void onActivityPaused(Activity activity) {}

@Override
public void onActivityDestroyed(Activity activity) {}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}}

Just create a singleton of this class and set it in your Application instance like below:

class App extends Application{
     @Override
     public void onCreate() {
         registerActivityLifecycleCallbacks(myAppActivityCallbacks);
     }
}

Then you can use isAnyActivityVisible() method of your MyAppActivityCallbacks instance everywhere!

Solution 12 - Android

Would Activity.onWindowFocusChanged(boolean hasFocus) be useful here? That, plus a class-level flag, something like isFocused that onWindowFocusChanged sets, would be an easy way to tell at any point in your activity if it is focused or not. From reading the docs, it looks like it would properly set "false" in any situation where the activity isn't directly in the physical "foreground", like if a dialog is being displayed or the notification tray is pulled down.

Example:

boolean isFocused;
@Override
void onWindowFocusChanged (boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    isFocused = hasFocus;
}

void someMethod() {
    if (isFocused) {
        // The activity is the foremost object on the screen
    } else {
        // The activity is obscured or otherwise not visible
    }
}

Solution 13 - Android

If you are using EventBus, it as a method called hasSubscriberForEvent which can be used to check if an Activity is focused.

Solution 14 - Android

I wanted to mention a modification. Activity.onPause kicks in even if your app is still partly visible (may be a system dialog box over it or split screen).

Maybe you'd want paused still count as visible and only count stopped/destroyed as invisible.

They you have a problem when your activity can restart (I have a restart button to counter some errors that don't occur often).

Even if it is the same activity it will not be destroyed before recreation but be handled like transitioning to another app:

This is not a direct answer to the question at hand but I noticed that the lifecycle displayed above is also true if you just terminate and restart the SAME activity (using a restart Button in a fragment in my case). This is true for Android 10 at least.

Restart process looks like this also: MainActivity (old) .onPause MainActivity (new) .onCreate MainActivity (new) .onStart MainActivity (new) .onResume MainActivity (old) .onStop MainActivity (old) .onDestroy

Now if you would set the visibility in onStop this has happened after onResume of the newer Instance of the activity and you wrongly get visibility false.

To counter that you can set a static string id in onCreate:

private static String instanceId = MainActivity.this.toString();

Then in onStop you can use

if(instanceId == null || instanceId.equals(MainActivity.this.toString()))
    setVisibility(false);
//else: visibility stays unchanged

Solution 15 - Android

did you try not calling finish, and putting "android:noHistory="true" in the manifest? this will prevent the activity from going to the stack.

Solution 16 - Android

I have to say your workflow is not in a standard Android way. In Android, you don't need to finish() your activity if you want to open another activity from Intent. As for user's convenience, Android allows user to use 'back' key to go back from the activity that you opened to your app.

So just let the system stop you activity and save anything need to when you activity is called back.

Solution 17 - Android

Save a flag if you are paused or resumed. If you are resumed it means you are in the foreground

boolean  isResumed = false;

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

@Override
public void onResume() {
  super.onResume();    
  isResumed = true;
}

private void finishIfForeground() {
  if (isResumed) {
    finish();
  }
}

Solution 18 - Android

One possible solution might be setting a flag while showing the system-dialog and then in the onStop method of the activity life-cycle, check for the flag, if true, finish the activity.

For example, if the system dialog is triggered by some buttonclick, then the onclick listener might be like

private OnClickListener btnClickListener = new OnClickListener() {
	
	@Override
	public void onClick(View v) {			
		Intent intent = new Intent();
		intent.setAction(Intent.ACTION_SEND);
		intent.setType("text/plain");
		CheckActivity.this.startActivity(Intent.createChooser(intent, "Complete action using"));
		checkFlag = true;  //flag used to check
		
	}
};

and in onstop of activity:

@Override
protected void onStop() {
	if(checkFlag){
		finish();
	}
	super.onStop();
}

Solution 19 - Android

Why not use broadcasts for this? the second activity (the one that needs to be up) can send a local broadcast like this:

//put this in onCreate(..) or any other lifecycle method that suits you best
//notice the string sent to the intent, it will be used to register a receiver!
Intent result = new Intent("broadcast identifier");
result.putString("some message");//this is optional
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result);

then write a simple receiver within the splash activity:

//this goes on the class level (like a class/instance variable, not in a method) of your splash activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //kill activity here!!!
        //mission accomplished!
    }
};

and register your new receiver with the LocalBroadcastManager to listen to the broadcast from your second activity:

//notice the string sent to the intent filter, this is where you tell the BroadcastManager which broadcasts you want to listen to!
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter("broadcast identifier"));

NOTE that you could use a constant or a string resource for the "broadcast identifier" string.

Solution 20 - Android

If you use finish() just to avoid new app to starts in the stack (task) of you app, you can use Intent.FLAG_ACTIVITY_NEW_TASK flag, when starting new application and do not call finish() at all. According to the documentation, this is the flag to be used to implement a "launcher" style behavior.

// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Solution 21 - Android

Use these methods inside of an Activity.

isDestroyed() > Added in Api 17
> Returns true if the final onDestroy() call has been made on the > Activity, so this instance is now dead.

isFinishing() > Added in Api 1
> Check to see whether this activity is in the process of finishing, > either because you called finish() on it or someone else has requested > that it finished. This is often used in onPause() to determine whether > the activity is simply pausing or completely finishing.


> From Memory Leaks Documentation

A common mistake with AsyncTask is to capture a strong reference to the host Activity (or Fragment):

class MyActivity extends Activity {
  private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
    // Don't do this! Inner classes implicitly keep a pointer to their
    // parent, which in this case is the Activity!
  }
}

This is a problem because AsyncTask can easily outlive the parent Activity, for example if a configuration change happens while the task is running.

The right way to do this is to make your task a static class, which does not capture the parent, and holding a weak reference to the host Activity:

class MyActivity extends Activity {
  static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<MyActivity> weakActivity;

    MyTask(MyActivity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      MyActivity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }
}

Solution 22 - Android

Here is a solution using Application class.

public class AppSingleton extends Application implements Application.ActivityLifecycleCallbacks {

private WeakReference<Context> foregroundActivity;


@Override
public void onActivityResumed(Activity activity) {
    foregroundActivity=new WeakReference<Context>(activity);
}

@Override
public void onActivityPaused(Activity activity) {
    String class_name_activity=activity.getClass().getCanonicalName();
    if (foregroundActivity != null && 
            foregroundActivity.get().getClass().getCanonicalName().equals(class_name_activity)) {
        foregroundActivity = null;
    }
}

//............................

public boolean isOnForeground(@NonNull Context activity_cntxt) {
    return isOnForeground(activity_cntxt.getClass().getCanonicalName());
}

public boolean isOnForeground(@NonNull String activity_canonical_name) {
    if (foregroundActivity != null && foregroundActivity.get() != null) {
        return foregroundActivity.get().getClass().getCanonicalName().equals(activity_canonical_name);
    }
    return false;
}
}

You can simply use it like follows,

((AppSingleton)context.getApplicationContext()).isOnForeground(context_activity);

If you have a reference to the required Activity or using the canonical name of the Activity, you can find out whether it's in the foreground or not. This solution may not be foolproof. Therefore your comments are really welcome.

Solution 23 - Android

I don't know why nobody talked about sharedPreferences, for Activity A,setting a SharedPreference like that (for example in onPause() ) :

SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();

I think this is the reliable way to track activities visibilty.

Solution 24 - Android

Since here you have explicitly asked for an Activity. I added a simple static method in my Utils class to get the state of the activity by passing the activity.

    public static boolean isActivityVisible(Activity mActivity) {
    if (mActivity != null) {
        Class klass = mActivity.getClass();
        while (klass != null) {
            try {
                Field field = klass.getDeclaredField("mResumed");
                field.setAccessible(true);
                Object obj = field.get(mActivity);
                return (Boolean)obj;
            } catch (NoSuchFieldException exception1) {
            Log.e(TAG, exception1.toString());
            } catch (IllegalAccessException exception2) {
            Log.e(TAG, exception2.toString());
            }
            klass = klass.getSuperclass();
        }
    }
    return false;
}

Solution 25 - Android

I used to do like,

if the activity is not in the foreground

> getIntent()

will return null. :=P

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
QuestionNickView Question on Stackoverflow
Solution 1 - AndroidBut I'm Not A Wrapper ClassView Answer on Stackoverflow
Solution 2 - AndroidsilvermouseView Answer on Stackoverflow
Solution 3 - AndroidAlex MisiuliaView Answer on Stackoverflow
Solution 4 - AndroidBurak DayView Answer on Stackoverflow
Solution 5 - AndroidMuzikantView Answer on Stackoverflow
Solution 6 - AndroidavianeyView Answer on Stackoverflow
Solution 7 - Androidkiran boghraView Answer on Stackoverflow
Solution 8 - AndroidKitView Answer on Stackoverflow
Solution 9 - AndroidEliasz KubalaView Answer on Stackoverflow
Solution 10 - AndroidRamzView Answer on Stackoverflow
Solution 11 - AndroidVasil StolyarchukView Answer on Stackoverflow
Solution 12 - AndroidInsanityOnABunView Answer on Stackoverflow
Solution 13 - AndroidKris BView Answer on Stackoverflow
Solution 14 - AndroidFrankKrumnowView Answer on Stackoverflow
Solution 15 - AndroidshaishView Answer on Stackoverflow
Solution 16 - AndroidOwen ZhaoView Answer on Stackoverflow
Solution 17 - AndroidyoahView Answer on Stackoverflow
Solution 18 - AndroidDiyaView Answer on Stackoverflow
Solution 19 - Androiduser1545072View Answer on Stackoverflow
Solution 20 - Androidsergej shafarenkaView Answer on Stackoverflow
Solution 21 - AndroidSanket BerdeView Answer on Stackoverflow
Solution 22 - AndroidTMtechView Answer on Stackoverflow
Solution 23 - AndroidHZDIView Answer on Stackoverflow
Solution 24 - AndroidSubhasmith ThapaView Answer on Stackoverflow
Solution 25 - AndroidJacob AbrahamView Answer on Stackoverflow