确定前台的应用程序是否是不受欢迎的?

时间:2012-12-26 18:20:54

标签: android activity-lifecycle application-lifecycle

有很多原因可以检测应用程序是否位于前台。 例如 - 作为GCM / C2DM推送通知的触发器 - 当应用程序是前台和后台时,许多应用程序将有充分的理由实现不同的行为。 其他原因可能是 - 击落消耗宝贵资源的服务,例如在后台任务中查询服务器。

为了清楚起见:背景应用的定义(我认为)
应用程序,其中没有任何活动被调用onStart()方法,并且尚未调用onStop()方法。 这是因为只有当时活动才能在用户生命周期中看到。

另一方面 -

  • 似乎Google不希望应用程序对主页按钮作出反应(它不是API的一部分)

  • 对“root / main”活动的onBackPressed()做出反应,作为离开Activity的指标肯定不是一个好主意(因为很多用户使用主页按钮,而不是后退按钮)

  • API中没有方法可以确定app是否为前景(根据我的定义..)

如果我没有错过API中的某些内容,而且确实如此 - 为什么没有原因可以轻松确定应用程序是否为前景???? !!!!

我知道我可以做以确定应用程序是否为前景在此主题中描述 - How to detect when an Android app goes to the background and come back to the foreground

但正如@Emil所说 - 它需要特殊许可,或者需要一些棘手的逻辑,这很快就会成为维护的问题,并且它闻起来像是糟糕的方法(虽然这就是我现在正在做的事情,因为我没有更好的主意......)

我的问题基本上是

  • 有充分理由没有这样的API方法吗?

  • 考虑应用程序是否为前景是一种不好的方法?

  • 有没有其他方法可以知道应用程序是否为前景?

4 个答案:

答案 0 :(得分:5)

  

是否考虑应用程序是否为前景是一种不好的方法?

将前景与背景考虑在内是合理的。

  

有没有其他方法可以知道应用程序是否为前景?

您可以将此方案粗略地分为两组:

  1. 您希望在前景/背景状态发生变化后立即采取行动

  2. 发生其他事件的情况(AlarmManager警报,传入系统广播等),此时您想根据您是否在前台采取不同的行动

  3. 在前一种情况下,onUserLeaveHint()是您最可靠的简单选项。我无法保证它将涵盖所有情况,但它应该处理HOME场景,例如。您也可以在静态数据成员中维护已启动活动的引用计数,并尝试使用它。

    在后一种情况下,ordered broadcast可能很有用。

答案 1 :(得分:1)

借助新的Android体系结构组件,您可以轻松地了解您的应用是前台还是后台。

就像活动范围生命周期所有者一样,您可以订阅并获得生命周期更新,这是一个通用的流程生命周期所有者。

例如:

添加此代码以注册为生命周期观察者

ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleListener)

此代码是为了接收相关的回调

@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onApplicationOnStartEvent() {

}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onApplicationOnStopEvent() {

}

别忘了在不需要时删除观察者

ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleListener);

更多信息和示例可以在这篇出色的文章中找到:

https://proandroiddev.com/detecting-when-an-android-app-backgrounds-in-2018-4b5a94977d5c

答案 2 :(得分:0)

我有同样的问题。我希望在活动未处于前台模式时显示推送通知。请仔细阅读以下代码,您将得到答案。

    Context ctx = context.getApplicationContext();

    ActivityManager am = (ActivityManager) context
            .getSystemService(ACTIVITY_SERVICE);

    // get the info from the currently running task
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

    PackageManager pm = this.getPackageManager();

    try {
        /**
         * take fore ground activity name
         */
        ComponentName componentInfo = taskInfo.get(0).topActivity;
        if (printLog == true) {
            Log.d("Home", "CURRENT Activity ::"
                    + taskInfo.get(0).topActivity.getClassName());
            Log.d("Home", "Number Of Activities : "
                    + taskInfo.get(0).numRunning);
            Log.d("Home",
                    "Componenet Info : " + componentInfo.getPackageName());
            Log.d("Home",
                    "Componenet Info : " + componentInfo.getClassName());
        }
        /**
         * All activities name of a package to compare with fore ground
         * activity. if match found, no notification displayed.
         */
        PackageInfo info = pm.getPackageInfo(
                "<PackageName>",
                PackageManager.GET_ACTIVITIES);
        ActivityInfo[] list = info.activities;

        for (int i = 0; i < list.length; i++) {
              Log.d("TAG","Activity : "+list[i].name);
        }

    } catch (NameNotFoundException e) {
        e.printStackTrace();
    }

要使用此功能,您必须获取manifest文件的权限。

使用权限android:name =“android.permission.GET_TASKS”

如果我无法回答您的问题,请原谅我。

答案 3 :(得分:0)

如果您需要知道应用程序是在背景上运行的服务的背景或前景(否则没有意义),那么您可以使用绑定,即 - 绑定到所有应用程序你的活动onResume,并取消绑定所有活动onPause。然后,在您的服务中,您不仅可以管理应用程序对用户的可见性,还可以随时管理哪些活动。它也是防漏的,比静态变量更稳定(如果需要的话可以清理),因为你正在使用android的API并且依赖于android OS代码本身的正确性。