【问题标题】:Stopping and starting a Service based on application state根据应用程序状态停止和启动服务
【发布时间】:2010-10-28 16:48:37
【问题描述】:

我有一个跟踪用户位置的服务。目前,服务在应用程序启动时启动,在应用程序终止时停止。不幸的是,如果用户将应用程序保持在后台,则服务永远不会停止并耗尽电池电量。

我希望服务在我的应用程序不在前台时停止。我希望 Application 类能让我覆盖 onPause 和 onResume 处理程序,但它没有它们。有没有其他方法可以做到这一点?

【问题讨论】:

  • 当您说“您的应用程序不在前台”时,您指的是与您的服务不同的 Activity(尽管我确定是同一个应用程序的一部分)?
  • 在服务的永无止境的循环中,添加一个检查以查看您的应用程序是否在前台。但这会花费您清单中的“GET_TASKS”权限。

标签: android service battery


【解决方案1】:

我还没有对此进行测试,但看起来如果您使用Context#bindService()(而不是Context#startService()),服务应该在没有更多活动绑定时停止。 (见Service lifecycle)。

然后在每个活动中使用onPause()/onResume() 来绑定/取消绑定服务。

或者,您可以在服务上添加一对方法,告诉它开始/停止侦听位置更新并从每个活动的onResume()/onPause() 调用它。该服务仍会运行,但位置更新不会耗尽电池电量。

【讨论】:

  • 有趣。我对 onPause/onResume 方法的唯一问题是,当启动一个新的 Activity 时,当前的 Activity 会在新的 Activity 恢复之前暂停。因此,启动一个新的 Activity 会停止服务。不过,您的第二个建议可能会奏效。
【解决方案2】:

阅读以上所有答案,我建议只需为每个活动添加一个布尔全局标志并将其放入您的 onResume 和 onPause 以及同时启动类似这样的活动

public void onPause()
{
super.onPause();
activity1IsResumed = true;
}

&onResume 也一样

& 启动新 Activity 时类似

startActivityForResult(myintent ,0);
activity2IsResumed = true;
activity1IsResumed = false;

然后在您的服务中简单地检查

if(activity1IsResumed || activity2IsResumed || activity3IsResumed)
{
//your logic
}
else
{
//another logic
//or dont run location tracker
}

&你完成了!

【讨论】:

    【解决方案3】:

    您应该覆盖Activity 上的onPauseonResume 方法。如果您有多个活动,您可能希望为它们创建一个公共基类,并将启动/停止逻辑放入基类中。

    【讨论】:

    • 所以您希望我的位置服务在我每次进入新屏幕时停止和启动?我认为这不是我想要的。
    • 您可以在自己的应用程序中启动活动时设置一个标志,并且只有在未设置启动自己的活动标志时才停止您的服务。
    【解决方案4】:

    我还没有尝试过这种方法,但我认为您可以使用 KeyEvent.KEYCODE_HOME 覆盖 android 设备的主页键,并且您可以使用 stopService(Intent) 停止您的服务,当应用程序再次恢复时,您可以在中写入 startService(Intent) Activity 的 onResume() 方法。

    这样我认为您的服务只会在用户明确按下主页按钮以在后台获取应用程序时停止,而不是在他从一个活动切换到另一个活动时停止。

    【讨论】:

      【解决方案5】:

      我的建议是覆盖其他人所说的 onPause/onReume 方法。如果不了解您的应用程序流程和活动之间的交互的更多信息,除了猜测之外,我无法提供更多信息。

      但是,如果您的活动是持久的,我的建议是在活动之间切换时更好地利用 Intent。

      例如,每个活动都应该有一个布尔“转换”标志。因此,当您从一个 Activity 移动到下一个 Activity 时,您设置了一个 Intent extra:

      intent.putExtra("transition",true);
      

      在接收Activity中跟随:(在onCreate中)

      intent.getBooleanExtra("transition",false);
      

      这样,对于每个启动的 Activity,您都可以知道它是来自另一个 Activity,还是从主屏幕启动器启动的。因此,如果它得到一个真正的转换,那么 onPause 不应该停止服务——这意味着你将在它返回后返回到前一个 Activity。如果它没有收到额外的“过渡”或错误的过渡,那么您可以放心地假设它下面没有 Activity 等待接管当前的。

      在第一个 Activity 上,如果您要切换到另一个 Activity,您只需停止服务,您应该能够以编程方式确定一个 Activity 是否从另一个 Activity 启动。

      【讨论】:

        【解决方案6】:

        听起来真正的问题是如何仅在您进行不属于您自己的活动时才停止服务?一种方法是在您的 onPause 方法中停止活动。为您的所有活动执行此操作。然后覆盖您的 startActivity 方法。并在这里做一个条件测试,以确认你是有目的地导航到你自己的。如果您将标志设置为 true。

        现在回到你的暂停覆盖方法。并且仅在标志不等于 true 时才停止您的服务。将标志设置为假。

        所有离开的事件都会关闭你的服务。导航到您自己的将保持原样。

        在所有活动都扩展的基类中进行覆盖。

        写在我的安卓里。稍后将发布ezaple。

        【讨论】:

          【解决方案7】:

          尝试使用绑定服务技术来完成此操作。

          Bound Services | Android Developers

          您可以使用绑定服务,使服务在没有活动绑定时停止。这样,当应用程序不在前台时,服务将不会运行。当用户将应用带回前台时,Activity 将绑定到服务,服务将恢复。

          【讨论】:

            【解决方案8】:

            在您的 Application 对象中创建方法 registerActivity()unRegisterActivity() 并在您的所有动作中实现第一个方法 onResume() 和第二个在动作 onPause() 中。

            第一种方法将活动添加到您的应用对象中的List<Activity> 实例,unRegisterActivity() 在每次调用if==0 stopService(); 时检查列表的大小。

            【讨论】:

            • 很有趣,但是这将如何工作?如果我启动一个新 Activity,前一个 Activity 的 onPause() 将在新 Activity 的 onResume() 之前执行。因此,计数将暂时 == 0,并且每次启动新 Activity 时服务都会停止。
            • 你是的,你可以在处理程序中检查大小。postDelayed(Runnable,500);或足以让所有活动暂停的延迟;试试这个,让我知道
            • 这个概念很好,但是添加活动引用到静态应用程序实例是导致内存泄漏的最简单方法。在您的注册/注销方法上增加一个计数器将是一种更好的方法,当计数器小于 0 时停止您的服务。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多