【问题标题】:Determine if application on foreground - is that frowned upon?确定应用程序是否在前台 - 这是否令人不悦?
【发布时间】:2012-12-12 05:51:15
【问题描述】:

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

明确一点:后台应用的定义(我认为)是
没有任何活动被调用 onStart() 方法的应用程序,并且还没有调用 onStop() 方法。 这是因为只有在那个时候,用户才能在其生命周期中看到活动。

另一方面——

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

  • 对“root / main”活动上的onBackPressed() 做出反应,作为离开Activity 的指标当然不是​​好主意(因为很多用户使用主页按钮,而不是返回按钮)

  • API 中没有方法可以确定应用程序是否为前台(根据我的定义..)

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

我知道我能做些什么来确定应用程序是否在前台在此线程中进行了描述 - How to detect when an Android app goes to the background and come back to the foreground

但正如@Emil 所说 - 它需要特殊许可,或者需要一些棘手的逻辑,这些逻辑很快就会变得难以维护,而且它闻起来像是不好的方法(尽管这就是我现在正在做的事情,因为我没有更好的主意...)

我的问题基本上是

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

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

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

【问题讨论】:

    标签: android activity-lifecycle application-lifecycle


    【解决方案1】:

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

    考虑前景与背景是合理的。

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

    您可以将其大致分为两组:

    1. 希望在前台/后台状态发生变化后立即采取行动的情况

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

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

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

    【讨论】:

    • 您的回答确实让我印象深刻……我没有考虑将有序广播作为第二种情况的解决方案。它似乎非常适合这种情况。关于第一种情况 - 我不熟悉 - onUserLeaveHint() 方法。很高兴知道它的存在,但正如你所说 - 它仍然没有涵盖所有内容。静态变量指示开始和没有停止的活动数量是我正在做的事情,并猜测在你的建议之后我会接受这个没有砍伐它这么糟糕的解决方案的解决方案.. :)
    【解决方案2】:

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

        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】:

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

    【讨论】:

      【解决方案4】:

      借助新的 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-22
        • 2011-12-17
        • 1970-01-01
        • 2012-10-03
        • 1970-01-01
        • 2016-09-21
        • 1970-01-01
        相关资源
        最近更新 更多