21

背景

我想使用 Lollipop 上提供的新 JobScheduler API,但遗憾的是它没有用于 pre-Lollipop 的官方端口。

但是,有 GcmTaskService,它提供了非常相似的功能。

问题

这个 API 很新,所以很少有地方可以找到如何使用它的信息(例如这里这里)。

问题

我对这个新 API 有几个问题:

  1. 似乎它需要使用 Google Play 服务(此处)(使用 Android 的 Lollipop 版本时除外,它将使用普通的 JobScheduler)。如果 Google Play 服务不可用,我该怎么办?

  2. 似乎即使我已将“setPersisted(true)”用于重复任务,但当我重新启动设备时,该任务将不会再次被调用。怎么会?编辑:那是因为我错过了 RECEIVE_BOOT_COMPLETED 的许可。

  3. 如果我不使用“setRequiredNetwork”,任务的默认行为是什么?是“NETWORK_STATE_ANY”吗?

  4. 文档说明了 onRunTask 返回的内容,我可以返回任何值“RESULT_FAILURE”、“RESULT_RESCHEDULE”、“RESULT_SUCCESS”(此处信息)。似乎 FAILURE 和 SUCCESS 选项都会做同样的事情 - 从队列中删除任务。这是真的吗?如果是这样,它们之间究竟有什么区别?它们的功能不同吗?

  5. TaskParams ”是否仅用于任务的标签?我可以使用 API 以某种方式将包传递给任务吗?否则,我需要设置一个数据库来存储应该传递给任务的内容,对吧?

  6. 应用程序是否可以获取任务队列?我知道可以使用 adb,但是也可以使用 API 吗?

  7. 他们说(这里)每个任务都有长达 3 分钟的唤醒锁。如果任务需要更多,应该怎么做?它应该为自己获取另一个唤醒锁吗?API 会警告唤醒锁已释放吗?这是文档所说的:

调度器会为你的服务持有一个 PowerManager.WakeLock,但是在执行三分钟后,如果你的任务没有返回,它将被认为已经超时,并且唤醒锁将被释放。此时重新安排您的任务将无效。如果您怀疑您的任务运行时间比这更长,您应该明确启动自己的服务或使用其他机制;此 API 旨在用于相对快速的网络操作。

  1. 他们说(在这里)每次应用程序升级/替换时都会删除所有网络任务,并且在发生这种情况时会调用“onInitializeTasks”,并且您可以再次重新安排它们。如何重新安排任务?我不认为我什至可以得到任务列表...

  2. 是否可以告诉任务更喜欢一天中的特定时间?例如,在 14:00-15:00 之间?

  3. 我注意到,如果您安排任务,然后强制停止和/或清除应用程序的数据,该任务仍将运行。我怎样才能避免这种行为?

4

2 回答 2

7

jacktech24 做得非常好,但如果有任何挥之不去的问题,我也会尝试。

  1. 似乎它需要使用 Google Play 服务(此处)(使用 Android 的 Lollipop 版本时除外,它将使用普通的 JobScheduler)。如果 Google Play 服务不可用,我该怎么办?*

    如果 Google Play 服务不可用,您将无法使用此 API。相反,Google Play 服务客户端库旨在请求用户在检测到它丢失时下载并安装 Google Play 服务,但我不相信 GcmNetworkManager 会这样做。

  2. 如果我不使用“setRequiredNetwork”,任务的默认行为是什么?是“NETWORK_STATE_ANY”吗?*

    javadoc 描述了哪个是默认值。

  3. 文档说明了 onRunTask 返回的内容,我可以返回任何值“RESULT_FAILURE”、“RESULT_RESCHEDULE”、“RESULT_SUCCESS”(此处为信息)。似乎 FAILURE 和 SUCCESS 选项都会做同样的事情 - 从队列中删除任务。这是真的吗?如果是这样,它们之间究竟有什么区别?它们的功能是否不同?*

    这两个之间的唯一区别是在 adb shell dumpsys 中它会显示您返回的内容,因此您可以使用它来解决问题。另一个原因是,如果任务失败,要求客户端返回“成功”是很奇怪的。

  4. “TaskParams”是否仅用于任务的标签?我可以使用 API 以某种方式将包传递给任务吗?否则,我需要设置一个数据库来存储应该传递给任务的内容,对吧?*

    在 GmsCore 的下一个版本中,应该支持将包添加到任务的功能。

  5. 应用程序是否可以获取任务队列?我知道可以使用 adb,但是也可以使用 API 吗?

    不,这是不可能的。相反,您应该在需要时执行取消,如果任务不存在,它将是空操作。同样,您应该在代码中查询任务列表的位置安排任务。使用 setUpdateCurrent=false 确保它不会更新预先存在的任务。AlarmManager 以类似的方式工作,无论是否已经设置了警报,您都可以设置警报 - api 旨在遵循这一点。

  6. 他们说(在这里)每个任务都有长达 3 分钟的唤醒锁。如果任务需要更多,应该怎么做?它应该为自己获取另一个唤醒锁吗?API 会警告唤醒锁已释放吗?这是文档所说的:*

    是的,应用程序应该获得自己的唤醒锁,一切都会好起来的。调度程序在 3 分钟后释放唤醒锁的原因是因为在实践中,无限唤醒锁超时只会导致很难追踪电池消耗错误。如果您需要超过 3 分钟的时间,那么您就有了一个足够复杂的用例,您可以深入了解 PowerManager API 的工作原理并自己调用 acquire()/release()(实际上非​​常简单,网络管理器会这样做)因为你比什么都更有礼貌)。

  7. 他们说(在这里)每次应用程序升级/替换时都会删除所有网络任务,并且在发生这种情况时会调用“onInitializeTasks”,并且您可以再次重新安排它们。如何重新安排任务?我认为我什至无法获得任务列表... *

    您重新安排任务的方式与最初安排的方式相同。无论您使用什么函数来调度它们,都可以从 GcmTaskService#onInitializeTasks 调用该函数。这样做是为了避免跨应用程序逻辑更改的延迟任务。考虑开发人员更改任务时间表并开始使用不同标签的情况。他们将被要求在检测到升级后调用 cancel(old_tag)(他们必须添加更多代码才能做到这一点),这意味着即使在他们的新代码。这意味着标签是一个稳定的标识符,不应该随着应用程序升级而改变——这不应该是这个 api 的要求。

  8. 是否可以告诉任务更喜欢一天中的特定时间?例如,在 14:00-15:00 之间?*

    不,这种类型的后台调度会导致跨大量设备群的各种问题。即,如果 1 台设备在 15:00 运行作业,那可能没问题。但是如果 1x10e6 突然出现,您的服务器就会出现严重问题。

  9. 我注意到,如果您安排任务,然后强制停止和/或清除应用程序的数据,该任务仍将运行。我怎样才能避免这种行为?*

    不幸的是你不能,但这不是故意的,应该改变 - 在用户明确停止后应用程序应该无法运行。

于 2015-07-16T03:34:09.690 回答
3

你可以在这里找到大部分问题的答案。

https://github.com/jacktech24/gcmnetworkmanager-android-example/blob/master/README.md

对于那里没有回答的答案

7:当唤醒锁被移除时你不会收到通知,正如他们在文档中所说,这个 API 只适用于短任务,如果你有更长的时间,编写你自己的实现

9:不,目前还不能,API 不允许

10:那是因为 Google Play 服务正在处理它,而且没有办法绕过它。您必须在服务中检测应用程序是否已设置(我希望这是您的问题),例如。创建配置等,并最终在调用其中之一时取消所有任务。

于 2015-07-15T11:10:52.240 回答