【问题标题】:How to detect if your android app is in the foreground (API 21)如何检测您的 android 应用程序是否在前台 (API 21)
【发布时间】:2014-10-19 23:07:21
【问题描述】:

当收到 GCM 消息时,我的应用的行为取决于它是否在前台。在 API 21 之前,我使用了以下内容:

Boolean onForeground = this.getPackageName().equalsIgnoreCase(
            ((ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE))
            .getRunningTasks(1).get(0).topActivity.getPackageName()
);

现在 getRunningTasks() 已被弃用,并且在 API 21 上的行为有所不同,在 API 21 上检测我的应用是否在前台的最佳方法是什么?

谷歌推荐

public ActivityManager.RecentTaskInfo getTaskInfo ()

但我不知道如何从那里获得所需的信息。

提前谢谢你。


编辑: 正如@CommonsWare 和@Chris Stratton 所提议的,我可以跟踪 onResume/onPause 状态。 WebView(我无法控制的内容)导致的应用程序崩溃会使系统处于错误状态。在这种错误状态下发送 GCM 会导致其他崩溃使用户感到困惑(他/她当时没有对我的应用执行任何操作)。

因此,我正在寻找另一种解决方案。 (我正在使用 Fragments 并且只有 1 个活动,因此实现这将是微不足道的)

【问题讨论】:

  • 使用事件总线让应用的 UI 层知道收到了 GCM 消息。让应用程序的 UI 层(活动/片段)在总线从前台进出时注册和注销。有一种方法可以确定 UI 层是否未处理该事件,并进行后台处理(例如,引发 Notification)。
  • 我有为三个事件总线实现此模式的示例:LocalBroadcastManager、Square 的 Otto 和 greenrobot 的 EventBus
  • 换句话说,一个 Activity 位于 onResume() 和 onPause() 之间的前台,一个应用程序是当它的 任何一个 Activity 是 - 你可以跟踪的东西通过让它们都调用或发送消息到一个公共组件中。
  • 感谢您的建议,这是我确实考虑过但想避免的事情,因为我有一个有时会导致应用程序崩溃的 web 视图(由于内容,我无法控制)。这种情况会离开错误的状态。 (将更新我的问题)

标签: android google-cloud-messaging android-5.0-lollipop


【解决方案1】:

您可以在您所在的位置使用ordered broadcast approach

  • 创建一个在您的清单中注册的 BroadcastReceiver,它执行后台行为
  • 在您的活动中以正优先级动态注册BroadcastReceiver(默认为0),确保在onStart()/onResume() 中注册并在onStop()/onPause() 中取消注册 -这是前台行为,应该调用abortBroadcast() 以确保不调用注册BroadcastReceiver 的清单

然后,您的 GCM 接收器可以使用 sendOrderedBroadcast() 发送广播(最好使用您的另一个 BroadcastReceivers 注册的自定义操作),动态注册的接收器(如果存在)和清单注册的接收器将接收该广播如果它不存在。

【讨论】:

  • 太好了,这正是我要找的。甚至不知道 sendOrderedBroadcast(),所以明天将有一些阅读要做。谢谢。
【解决方案2】:

我使用getRunningAppProcesses 检测到

boolean isOnForeground = 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()))
                {
                    isOnForeground = false;
                }
            }
        }
    }
}
else
{
     List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
     ComponentName componentInfo = taskInfo.get(0).topActivity;
                if(componentInfo.getPackageName().equals(context.getPackageName()))
     {
          isOnForeground = false;
     }
}

【讨论】:

  • 应用程序进程即使不在前台也可以具有前台优先级/重要性。 OP 想知道他们的应用程序是否真的在前台,所以这不起作用。例如。一个没有可见 Activity 的进程,它有一个使用 startForeground 的 Service 将具有前景重要性。另外,您返回的不是与您想要的相反吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 2016-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多