在方向更改期间保持服务运行

时间:2011-12-02 18:06:35

标签: android

在我的应用程序中,我有一个Service,它负责管理与外部设备的蓝牙连接。此Service类定期轮询外部蓝牙设备的数据,并将最新数据添加到缓存(或可能是SD卡)内存中的日志中。

在我拥有的各种Activity类中,有一个特定的Activity代表主UI。它负责以图形形式显示基于缓存文件数据的记录数据。我们称之为Activity Dashboard。用户可以在该图表上来回滚动,以查看自应用程序启动以来在缓存中收集和记录的数据。

出于这个问题的目的,有两种操作模式需要考虑。用户可以选择“登录到SD卡”选项,即使所有Activity类都被杀死,应用程序也必须继续轮询并记录到SD卡(例如,用户已经返回到发射器)。在这种情况下,我的Service使用.startService()启动并继续运行,并且只有在用户再次调用应用程序并禁用SD卡日志记录时才会停止。另一种模式是用户没有选择“登录到SD卡”,在这种情况下,Service仍在管理蓝牙连接,轮询和记录到高速缓冲存储器,以便在视觉上显示数据。图表,但只需要在使用Dashboard Activity时执行此操作。

我目前所拥有的是Dashboard Activity最初使用Service绑定到bindService(),并在unbindService()内对onPause()进行相应的调用Service方法(否则我会泄漏Service)。

问题是Activity需要保持蓝牙连接并在方向更改期间或用户通过顶部调用另一个startService()时继续记录(例如检查电子邮件)。现在,如果用户选择了“登录到SD卡”,导致拨打Activity,那么当然没有问题。问题当然是如何区分被销毁的Service然后由于方向(或其他一些配置)的变化而再次创建,并且因为用户返回到启动器而被销毁。在前一种情况下,我不希望Service数据记录被中断。在后一种情况下,我希望startService()停止,如果用户没有选择“登录到SD卡”。

目前我能想到的最佳解决方案是使用Dashboard 始终启动服务,以便在Service时继续运行已被摧毁。我会做的是在Service内实施超时,Dashboard将自行停止,除非连续SD卡日志已启用, onCreate在{5}内再次Service d(比如说)并重新绑定到{{1}}。这似乎有点粗糙,我不禁想到这一定是一个常见的设计问题,有一个我忽略的更好的解决方案。

4 个答案:

答案 0 :(得分:6)

选项1:如果您希望在主要活动结束时立即销毁服务。

在绑定之前手动启动时,服务不会被销毁:

protected void onStart() {
  Intent intent = new Intent(getApplicationContext(), MServcie.class);
  startService(intent);
  bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

仅在您的活动完成时停止服务!

protected void onStop() {
  if (service != null) {
    unbindService(connection);
    service = null;
    if (isFinishing()) {
      stopService(new Intent(getApplicationContext(), MyServcie.class));
    }
  }
}

选项2:如果您希望操作系统决定何时停止服务。

protected void onStart() {
    Intent intent = new Intent(this, MServcie.class);
    getApplicationContext().bindService(intent, this, Context.BIND_AUTO_CREATE);
}

答案 1 :(得分:4)

您可以使用的一种方法是在isFinishing()解除绑定之前检查活动onPause()。如果它正在完成,您可以将解除绑定推迟到onDestroy()方法。但是,在调用onDestroy()之前,您可以使用onRetainNonConfigurationInstance()方法保留ServiceConnection。如果你确实执行了持久性,那么根本不会在你的unBind()内部实际调用onDestroy(),只需让你的Activity的新实例进行解除绑定。

话虽如此,根据您的应用程序,您可能会发现启动/停止服务更容易。

答案 2 :(得分:3)

正如您可能已经知道的那样,服务实际上是为了与活动建立单独的生命周期。因此,您可以考虑不将纯服务用于纯粹的监控方案。在背景情况下,您只需要与活动分开的生命周期,但在纯粹的监控情况下则不需要。

真正想要的是您的日志记录与应用程序的生命周期相关联,并且您可以通过启动/停止活动或您的活动来控制应用程序的生命周期服务。如果您在可从Application对象访问的单独线程中进行轮询,则您的Activities根本不需要与Service绑定,而只需与此日志记录线程进行通信。当您确实需要后台日志记录时,您可以启动/停止服务,该服务还可以与日志记录线程进行通信,以便在停止时正常清理,正确重新启动等等。

答案 3 :(得分:3)

您应该使用isChangingConfigurations(),而不是isFinishing():后者是false,如果活动失去了可见性,配置发生变化,那么您无法区分。< / p>