How to check if activity is in foreground or in vi

2020-01-23 02:32发布

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.

22条回答
Root(大扎)
2楼-- · 2020-01-23 02:58

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();
  }
}
查看更多
祖国的老花朵
3楼-- · 2020-01-23 02:59

I used to do like,

if the activity is not in the foreground

getIntent()

will return null. :=P

查看更多
Bombasti
4楼-- · 2020-01-23 03:00

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()
查看更多
虎瘦雄心在
5楼-- · 2020-01-23 03:03

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.

查看更多
你好瞎i
6楼-- · 2020-01-23 03:05

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.

查看更多
姐就是有狂的资本
7楼-- · 2020-01-23 03:06

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.

查看更多
登录 后发表回答