【问题标题】:Posting data to server every 15 minutes using Sync Adapter and Alarms使用同步适配器和警报每 15 分钟将数据发布到服务器
【发布时间】:2016-02-11 13:27:11
【问题描述】:

要求 - 我需要大致每 15 分钟获取一次用户的位置坐标并将其发布到服务器。有必要大致按这些间隔发布数据。

实现 - 我制作了一个同步适配器,而不是使用 AlarmManager,因为它可以节省电池。我已将ContentResolver.addPeriodicSync() 设置为大致每 15 分钟同步一次我的应用程序,从而获取当前位置并发布到服务器。

问题 - 如果没有互联网连接,我想继续每 15 分钟获取一次用户的位置并将其保存在本地 sqlite 数据库中。下次网络恢复时,我会一次性发布所有保存的位置,以便服务器数据保持一致,之后同步恢复正常。

主要问题是,当没有互联网时,同步停止,我的应用程序中不再收到定期同步回调,并且我无法将数据保存在本地数据库中。所以我想要的是,即使没有互联网,我也会定期收到回调,直到互联网恢复并再次开始自动同步。同步适配器能做到吗?

我能想到的一个解决方案是当互联网停止时我会收到一个广播,然后我开始使用AlarmManager每15分钟启动一次服务并获取位置并保存到本地数据库。当互联网恢复正常时,我会停止使用 AlarmManager 并返回自动同步。

解决方案 2 - 由下面的 David Medenjak 提供。由于 AlarmManager 的 setInexactRepeating() 行为试图模仿 Sync 适配器的行为,通过将不同应用程序的警报安排在一起来减少 CPU 唤醒的次数,它也很有效。它也导致了更简单的实现。这会比之前比较利弊的解决方案更好吗?

还有更好的方法来实现这一点吗?

【问题讨论】:

  • 您使用的是平台的LocationServices API 还是 Google Play Services 的定位服务?
  • 来自 Google Play 的定位服务。
  • 您是在使用FusedLocationApi.getLastLocation 还是通过PendingIntent 订阅持续交付?
  • 每当同步开始时,我都会使用 FusedLocationApi.getLastLocation 获取位置并发送到服务器。
  • 你找到答案了吗

标签: android android-sqlite alarmmanager android-syncadapter


【解决方案1】:

你混合了两件事:

  • 每 15 分钟获取一次用户位置
  • 与服务器同步数据

如果你开始混合那些你有一个相互依赖的服务和同步适配器,你必须检查哪些状态已经运行,哪些应该运行。您最终可能会得到您想要的确切内容(每 15 分钟同步一次,如果用户离线,只需将其缓存),但很难测试和维护。


始终使用每 15 分钟运行一次的服务来存储当前用户位置。

定期将所有更新同步到服务器。这也可能每 15 分钟发生一次,但您不应依赖此。

通过让一部分仅存储位置而另一部分仅同步数据,您将更容易处理事情。而且您也不必担心互联网连接或同步间隔(因为不能保证同步适配器在准确的时间运行)。


关于电池寿命 (cmets)

SyncAdapter 使用 gps 并立即发布或服务暂时保留它直到适配器同步它应该没有太大区别。一旦任务必须每 x 分钟运行一次,设备就必须唤醒。

如果与服务相比,同步运行的速度较慢,则可能会有轻微的改进,因为单独的 gps可能不需要任何互联网连接。

【讨论】:

  • 你说得对,它会产生相同的效果,我最终会每 15 分钟同步到服务器,但是当互联网处于活动状态并假设它会在大多数情况下,不会运行同步适配器而不是带有唤醒锁的服务不是更好(电池方面)。当同步适配器运行时,我让它完成获取位置和发布它的所有工作。那么值得付出努力还是不明智?因为正如您所说,全职运行服务很简单。但是如果我运行一项服务,那么同步适配器的意义何在?我也可以发布该服务的数据吗?谢谢!
  • @JyotmanSingh 如果您需要它每 15 分钟运行一次,同步适配器也会保持设备唤醒。它不能在设备休眠时运行,服务也不能。你可能有一些开销,但你不会真正节省多少能源。 注意: 不要“全时”运行服务,而是每 15 分钟启动一次以运行并完成其工作。此外,您还可以通过较少的同步(例如每天一次)节省一些能量,因为仅 gps 可能不需要创建互联网连接(这使用电池)
  • 是的,我将通过 AlarmManager 每 15 分钟使用一次服务,是的,同步适配器也会唤醒设备进行同步,但它不会更有效,因为它会尝试匹配同步时间与其他应用程序为好。它不会唤醒设备,尤其是对于我的设备。我不介意15分钟变成20分钟还是10分钟。而且我无法每天同步一次,因为我需要每 15-20 分钟向服务器提供一次更新。
  • @JyotmanSingh 您还可以设置警报管理器在不准确的时间调用您的服务以匹配其他应用程序,是的,您是对的,它可能效率稍高一些,但是您将很难编写和维护它
  • 我不知道 AlarmManager 的 setInexactRepeating()。我想它也可以节省一些电池。我想我会尝试这两种方法并进行比较,同时看看是否有其他更好的解决方案出现。实施该方法后,我会尽快与您联系。感谢您的意见。
【解决方案2】:

IntentService - 每 15 分钟运行一次(使用 AlarmManager)并将用户位置保存在数据库中并将其标记为未发送。

SyncAdapter - 每 15 分钟运行一次,并将所有未发送的位置发送到服务器。成功时将位置标记为已发送。 Android 将确保它仅在有互联网连接时运行。

编辑:
关键是将两个子任务分开(@David Medenjak 也建议):
1) 获取位置更新并将其存储在数据库中
2) 当有网络连接时,将位置更新发送到服务器。

FusedLocationProvider 有一个方法

requestLocationUpdates (GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)

当您的应用处于后台时。 Link

此方法适用于后台用例,更具体地说 用于接收位置更新,即使应用程序已被 系统。

您可以使用LocationRequest 设置优先级、间隔、功耗。 Link

当您收到待处理的意图时,您可以在数据库中插入位置并使用同步适配器请求同步。

【讨论】:

  • 是的,这就是我已经提到的解决方案。如果有的话,我正在寻找更好的方法。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多