如何检查活动是在前景还是在可见背景中?

Nic*_*ick 98 android dialog activity-finish android-activity

我在计时器上有一个闪屏.我的问题是,在finish()我的活动之前,我需要检查下一个活动是否已经开始,因为系统对话框弹出,我只想finish(); 一旦用户从对话框中选择了一个选项?

我知道有很多关于如何查看您的活动是否在前台的问题,但我不知道这是否允许在活动之上设置对话框.

这是问题,红色是我的活动,它在后台,而对话在前台:

当对话在前景时,红色是我的活动

编辑:我已经尝试过不使用finish()但是我的活动可以回到我试图避免的应用程序堆栈中.

But*_*ass 180

这是推荐的正确解决方案:

正确的解决方案(积分归Dan,CommonsWare和NeTeInStEiN)使用Activity.onPause,Activity.onResume方法自行跟踪应用程序的可见性.将"可见性"状态存储在其他类中.好的选择是您自己的应用程序或服务实现(如果您想检查服务的活动可见性,还有一些此解决方案的变体).

示例 实现自定义Application类(请注意isActivityVisible()静态方法):

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;
}
Run Code Online (Sandbox Code Playgroud)

在AndroidManifest.xml中注册您的应用程序类:

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >
Run Code Online (Sandbox Code Playgroud)

将onPause和onResume添加到项目中的每个Activity(如果您愿意,可以为您的活动创建一个共同的祖先,但如果您的活动已经从MapActivity/ListActivity等扩展,您仍然需要手动编写以下内容) :

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

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}
Run Code Online (Sandbox Code Playgroud)

在您的finish()方法中,您希望用于isActivityVisible()检查活动是否可见.在那里,您还可以检查用户是否选择了选项.满足两个条件时继续.

该消息来源还提到了两个错误的解决方案......所以避免这样做.

来源:stackoverflow

  • 这不能可靠地工作.您可能遇到以下情况:恢复A恢复B暂停A.现在activityVisible为false,而应用程序是可见的.也许您使用可见性计数器:onResume中的visibleCounter ++和onPause中的visibleCounter. (24认同)
  • 同意_Joris Weimar_认为这不是一个万无一失的解决方案.一种情况是如果用户拉下通知面板,则不会调用`onPause`,`onStop`和`onResume`事件.那么,如果没有这些事件被解雇,你会怎么做?! (4认同)
  • 如果app有多个Activity,则此方案无效.至少更换柜台 (2认同)

Him*_*ani 67

如果定位API级别14或更高级别,可以使用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
    ....
}
Run Code Online (Sandbox Code Playgroud)

  • 您也可以在常规活动生命周期回调(onResume(),onStop())中执行此操作. (17认同)
  • @DanielWilson我认为关键不是要建立一个已经存在的系统来做某事。恕我直言,这应该是公认的答案。 (3认同)

Ale*_*lia 14

UPD:已更新为状态Lifecycle.State.RESUMED。感谢@htafoya

在2019年,借助新的支持库28+或AndroidX,您可以简单地使用:

val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
Run Code Online (Sandbox Code Playgroud)

您可以在文档中阅读更多内容,以了解幕后发生的事情。

  • 并非如此,放置“ activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)”或“ STARTED”可能更好。“ INITIALIZED”并不能保证它位于前台。 (2认同)

Muz*_*ant 10

这正是Activity类文档中描述的活动onPauseonStop事件之间的区别.

如果我理解正确,您要做的就是finish()从您的活动中调用onStop以终止它.请参阅活动生命周期演示应用程序的附图.这是它的外观,当活动B从活动A.事件的顺序是从下到上,所以你可以看到,活动一推出像onStop后,活动B被称为onResume已经调用.

活动生命周期演示

如果显示对话框,则您的活动在后台变暗并且仅onPause被调用.


Bur*_*Day 9

Activity :: hasWindowFocus()返回您需要的布尔值.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例课程,用于检查您的活动在任何地方的可见性.

请记住,如果显示对话框,则结果将为false,因为对话框将具有主焦点.除此之外,它比建议的解决方案更方便,更可靠.


avi*_*ney 7

两种可能的解决方

1)活动LifeCycle回调

使用实现ActivityLifecycleCallbacks应用程序,并使用它来跟踪应用程序中的活动生命周期事件.请注意,ActivityLifecycleCallbacks适用于Android api> = 14.对于以前的Android API,您需要在所有活动中自行实现;-)

需要在活动中共享/存储状态时使用应用程序.

2)检查运行过程信息

您可以使用此类RunningAppProcessInfo检查正在运行的进程的状态

使用ActivityManager.getRunningAppProcesses()获取正在运行的进程列表, 并过滤结果列表以检查所需的RunningAppProcessInfo并检查其"重要性"