【问题标题】:Android: How to detect if current stack of activities (task) moves to background?Android:如何检测当前的活动堆栈(任务)是否移动到后台?
【发布时间】:2012-07-24 05:49:17
【问题描述】:

官方文档对任务的描述如下:

*任务中的所有活动作为一个单元一起移动。整个任务(整个活动堆栈)可以被带到前台或发送到后台。例如,假设当前任务在其堆栈中有四个活动——三个在当前活动下。用户按下 HOME 键,进入应用程序启动器,然后选择一个新应用程序(实际上是一个新任务)。当前任务进入后台并显示新任务的根活动。然后,在短时间内,用户返回主屏幕并再次选择上一个应用程序(上一个任务)。该任务连同堆栈中的所有四个活动一起出现。

有没有办法以编程方式检测当前 Activity 的任务何时移入和移出后台?我想知道用户何时切换到另一个应用程序,以及用户何时导航到当前应用程序中的另一个 Activity。

【问题讨论】:

  • 如果您能告诉我们检测的目的是什么可能会有所帮助?
  • 我的业务逻辑根据这两种情况是不同的。后台活动在后台绑定到远程服务。如果用户实际上是在切换任务,我希望这个后台活动解除绑定。否则,它需要保持绑定才能将服务公开给我的应用程序中的其他活动。

标签: android


【解决方案1】:

注意:我一直有这个设计,但从来没有进行过具体的测试(虽然可以肯定它有效),所以如果你最终尝试了这个,告诉我它是怎么回事。 :)


我认为没有官方 API 方法可以为您提供此功能(我可能错了),但您当然可以构建自己的。这只是我的做法;当然,可能会有更好的实现。

在您的应用程序中,您总是知道何时开始另一个活动。话虽如此,您可以创建一个全局类来处理启动所有应用程序活动并跟踪表示您何时启动活动的布尔值:

public class GlobalActivityManager {

    private static boolean isActivityStarting = true;

    public static boolean isActivityStarting() {
        return isActivityStarting;
    }

    public static void setIsActivityStarting(boolean newValue) {
        isActivityStarting = newValue;
    }

    public static void startActivity(Activity previous, Class activityClass) {
        isActivityStarting = true;
        // Do stuff to start your activity
        isActivityStarting = false;
    }
}

然后在您的每个活动中(可能将其设为超类),重写 onPause() 方法以检查它是您的应用程序的另一个活动开始还是外部任务的应用程序在您的应用程序前面。这是有效的,因为当活动前面有任何内容时会执行 onPause,这意味着当您在 GlobalActivityManager 中启动活动时调用它,其中 isActivityStarting 为真。

public void onPause() {
    super.onPause();
    if (GlobalActivityManager.isActivityStarting()) {
        // It's one of your application's activities. Everything's normal.
    } else {
        // Some other task has come to the foreground. Do what needs to be done.
    }
}

【讨论】:

  • 看看 James 在下面所说的关于后退按钮的内容,这将导致当前(前台)Activity 的 onPause 方法在没有 startActivity 时被调用。所以可能会覆盖后退按钮(我认为这是可能的)以适当地检测到这一点。但总的来说,这里似乎需要做更多的工作。
【解决方案2】:
    public boolean isCurrentTaskInBackground() {
    List<RunningTaskInfo> taskInfoList = mActivityManager.getRunningTasks(1);
    if (taskInfoList != null && taskInfoList.size() > 0) {
        RunningTaskInfo info = taskInfoList.get(0);

        ComponentName componentName = info.baseActivity;

        MobileTvLog.debug("App#isCurrentTaskInBackground -> baseActivity = " + componentName);

        String packageName = componentName.getPackageName();

        return !YOUR_PKG_NAME.equals(packageName);
    } else {
        return true;
    }
}

【讨论】:

    【解决方案3】:

    也许这会有所帮助,告诉我它是否对你有用。 仅当您从后台返回时,活动的值才会为 0(零) 当 onRestart() 被执行。

    public class FatherClass extends Activity {
    
    private static int activities = 0;
    
    public void onCreate(Bundle savedInstanceState, String clase) {
        super.onCreate(savedInstanceState);
    }
    
    protected void onRestart()
    {
        super.onRestart();
        if(activities == 0){
            Log.i("APP","BACK FROM BACKGROUND");
        }
    }
    
    protected void onStop(){
        super.onStop();
        activities -= 1;
    }
    
    protected void onStart(){
        super.onStart();
        activities += 1;
    }
    

    }


    您的所有类都必须从此类扩展才能使其工作。

    【讨论】:

    • 静态变量可以在android下被垃圾收集(你没有注意到它)并且可以在你按下主页按钮时被重置。此实现保证在某些时候会失败。
    • 就像你说的那样,主页按钮可以将它设置回 0,这正是你想要的,在这种情况下,当你退出整个应用程序时它是 0,通常垃圾收集器也会删除它当您转到其他应用程序时,变量更合理,然后当您返回时可能会发生这种情况,但您再次得到您想要的确切结果(变量为 0)。但是您是对的,即使在您自己的应用程序内部,垃圾收集器也可能会删除您的变量,但我认为这不太可能发生。
    • 这是一种可能的情况。只需使用一些内存不足的 2.2 手机并推送新的 Activity。
    【解决方案4】:

    那是行不通的。除了您的应用明确启动另一个活动之外,您的活动可能会因为其他原因而获得 onPause。例如,用户可能点击了后退按钮,将您带回到堆栈中的上一个 Activity。

    【讨论】:

    • 你没有回答问题,是吗?
    【解决方案5】:

    尝试阅读有关 android:finishOnTaskLaunch 的信息

    http://developer.android.com/guide/topics/manifest/activity-element.html#finish

    它解决了我的类似问题;-)

    【讨论】:

      【解决方案6】:

      我一直在寻找这个问题的好答案。看起来 Andy Zhang 有一个好主意,但它可能需要更多的工作来处理其他事情,比如返回按钮。

      另一种看起来很有前途的方法是使用 ActivityManager.getRunningAppProcesses() 方法,它会为您提供一个 RunningAppProcessInfo 列表,每个列表都有一个“重要性”变量,可用于检测您的进程是否在前台或其他州。

      问题当然是这里没有检测技术,只是一种告诉正在运行的内容及其状态的方法,但无法在状态发生变化时得到通知。

      所以可能只是运行一个后台线程来轮询此信息。看起来有点笨拙,但它可能会起作用。

      我的应用程序使用定位服务 (GPS),因此当位置发生变化时它会自动被调用,并且我可以在发生这种情况时检查 RunningAppProcessInfo 列表以确定我的应用程序是否仍在前台。看起来工作量很大,所以也许可以改进 Andy 的方法。

      【讨论】:

        【解决方案7】:

        我一直在使用我在这里描述的方法:

        Simple check for Android application backgrounding

        它对我来说效果很好。

        【讨论】:

          【解决方案8】:

          您也许可以在 onPause() 中使用 isFinishing() 方法。这将告诉您应用程序是否真正完成或只是被暂停。当您的任务堆栈进入后台时,活动还没有完成,它们只是暂停了。但是,如果您从该活动开始另一个活动,这也会被调用,因此您必须检查它。

          @Override
          public void onPause() {
              super.onPause();
              if(!isFinishing()) {
                  //app going to background
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-16
            • 2017-03-07
            • 2014-03-18
            • 1970-01-01
            相关资源
            最近更新 更多