关于GcmTaskService的一些问题

21

背景

我想使用在Lollipop上介绍的新的JobScheduler API,但很遗憾它没有官方的pre-Lollipop版本。

不过,有GcmTaskService,提供非常相似的功能。

问题

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

问题列表

  1. 看起来需要使用Google Play服务(这里)来使用它(除了使用Android Lollipop版本的设备外,它将使用正常的JobScheduler)。如果没有Google Play服务怎么办?

  2. 虽然我对一个重复的任务使用了"setPersisted(true)",但当我重新启动设备时,任务不会再次被调用。为什么?编辑:因为我错过了RECEIVE_BOOT_COMPLETED权限。

  3. 如果我没有使用"setRequiredNetwork",任务的默认行为是什么?是"NETWORK_STATE_ANY"吗?

  • 这个文档中提到了onRunTask返回的值,我可以返回"RESULT_FAILURE"、"RESULT_RESCHEDULE"或"RESULT_SUCCESS"中的任意一个(更多信息请参见此处)。似乎FAILURE和SUCCESS选项会做相同的事情——从队列中删除任务。这是真的吗?如果是,它们之间的区别究竟是什么?它们的功能不同吗?

  • "TaskParams"只用于任务的标签吗?我能否通过API传递bundle给任务?否则,我需要设置一个数据库来存储应传递给任务的内容,正确吗?

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

  • 他们在这里说(此处)每个任务有一个长达3分钟的唤醒锁。如果任务需要更长的时间怎么办?它应该为自己获取另一个唤醒锁吗?API会警告唤醒锁已释放吗?文档中的说明如下:

  • 调度程序将为您的服务持有PowerManager.WakeLock, 但是执行3分钟后,如果您的任务没有返回,它将被视为超时,并且唤醒锁将被 释放。此时重新安排你的任务将没有任何效果。如果 您怀疑您的任务将运行时间比这更长,您应该显式地启动自己的服务或使用其他机制;此API旨在用于相对较快的网络操作。

    1. 他们在这里说(这里),每当应用程序升级或替换时,所有网络任务都会被删除,并在此发生时调用“onInitializeTasks”,您可以重新安排它们。我如何重新安排任务?我认为我甚至无法获取任务列表...

    2. 是否可能告诉任务在一天中的特定时间段内偏好特定的时间?例如,在14:00至15:00之间?

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

    2个回答

    7

    Jacktech24做得非常好,但为了防止有任何未解决的问题,我也会尝试。

    1. 看起来使用该API需要使用Google Play服务(此处),除非使用Android的Lollipop版本,它将使用正常的JobScheduler。如果Google Play服务不可用怎么办?*

      如果Google Play服务不可用,则无法使用此API。相反,Google Play服务客户端库旨在请求用户下载和安装Google Play服务,如果检测到缺少Google Play服务,但我不认为GcmNetworkManager会这样做。

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

      文档中描述了默认值。

    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调用该功能。这是为避免跨应用逻辑更改


    1. 它不行。很遗憾,要求没能满足。
    2. 是的,后来注意到了。正在连接中。
    3. 我明白了。
    4. 什么时候发布?你怎么知道这个消息?还会添加哪些其他功能?
    5. JobScheduler可以实现,但GcmNetworkManager不行。
    6. 很好,谢谢。
    7. 问题是,你需要跟踪应该被调度的内容及其参数(例如,发送文件将需要知道哪个文件以及发送到哪里)。关于你的解释,这仍然没有意义,因为它只针对网络任务。关于旧标签和新标签,这是需要管理的事情,就像数据库更改一样。
    - android developer
    1. 我的意思是它可以像不精确的警报一样工作。操作系统/框架应该决定何时运行每个任务,它们可以批量执行。算法已经尝试在特殊条件下运行任务。时间条件只是一个容易检查的简单条件。我并不是说所有任务都会同时运行,我认为算法不会这么轻易地实现这一点。
    2. 好的。
    3. 你也知道这个吗?有时候我需要告诉API:“如果可能的话现在就执行,或者稍后再执行”。
    - android developer
    1. 我曾经在JobScheduler + GcmNetworkManager + SyncManager上工作过。
    2. 我理解你的观点关于发送文件。基本上,如果你安排了一个任务,然后你的应用程序升级了,任务就不会运行。这以前并不是很重要,因为API的限制(你只能提供一个标签,并且预计将任何需要的参数存储在本地)。然而,考虑到您将能够在任务上设置Bundle,这个问题应该得到解决。
    - 43matthew
    1. 很好。那么它很快就会发布了吗?我还注意到,对于JobScheduler,我可以立即运行任务,但GcmNetworkManager不允许这样做,它会在你告诉它后大约30-60秒运行任务。
    2. 为什么它只取消网络任务(而且完全取消)?此外,为什么JobScheduler具有这种行为(或者看起来是这样)?
    3. 它也会被添加吗?
    4. 第一篇帖子有这个问题:“我注意到如果你安排一个任务,然后你强制停止和/或清除应用程序的数据,任务仍然会运行。我该如何避免这种行为?”
    - android developer
    我认为JobScheduler还存在另一个问题:所有作业的ID是否都需要唯一,即使是从扩展自JobService的非常不同的类中继承而来的?例如,如果我有ID为0的Job1,并且它在JobService1上运行,那么我不能在JobService2上拥有相同ID的Job2吗? - android developer
    显示剩余4条评论

    3

    在这里,您可以找到大多数关于IT技术的问题的答案。

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

    对于那些没有在上述链接中得到解答的问题:

    7:当wakelock被移除时,您将不会收到通知。正如文档所说,此API仅适用于短期任务,如果您有更长时间的任务,请编写自己的实现。

    9:现在还不行,该API不允许。

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


    1. 如果不可用,则需要额外的代码。
    2. 好的,它需要RECEIVE_BOOT_COMPLETED权限。
    3. 好的,所以默认是连接的。
    4. 我认为你弄错了。无论失败还是成功都应该重新安排任务。
    5. 很遗憾,JobScheduler确实有这个功能。而且,把它放在Application类(或任何其他地方)是错误的,因为即使设备重新启动,你也需要恢复它,所以你需要一个真正的存储方法。
    6. 不幸的是,这又是只有在JobScheduler上才能使用的东西。
    7. 如果我持有另一个WakeLock会发生什么?
    - android developer
    1. 由于失败而引起的重新调度由“RESULT_FAILURE”、“RESULT_RESCHEDULE”设置,但我想知道失败和成功之间有什么区别,因为两者似乎具有相同的行为。对于两者来说,任务都将从队列中删除,如果任务是周期性的,则会添加另一个任务。关于OneOff任务,如果它是重新调度还是不重新调度,为什么需要另一种可能的选项?
    2. 你指出它应该在Application类中,但实际上并不重要,因为数据的来源不是来自那里,而是来自真正的存储。对于你来说,它只是一个缓存位置...
    - android developer
    目前我是@androiddeveloper,对于失败和成功之间没有太大的区别,唯一知道的是当你使用命令打印排队任务等时,会有统计数据(FAILED / SUCCESS等)。关于Application类,是的,你是正确的,在Github上的示例中我已经修复了它。至于时间,网络连接可能会很慢,也许Google将来会允许以某种方式克服这个问题,但我认为大多数连接都可以适应那个时间间隔。如果你正在下载大量数据,可以在创建任务时要求WIFI连接。 - filipproch
    1
    我明白了。我一定要告诉谷歌这些缺失但非常重要的功能。他们至少应该具有与JobScheduler相同的功能。感谢您的时间。 - android developer
    根据文档,最短等待时间为30秒。请注意,您可以请求在未来的任何时间执行一次性任务,但为了防止滥用,调度程序将仅在未来最少30秒设置警报。如果发生某些网络事件以唤醒调度程序,则仍然可以提前运行您的任务。 - sakis kaliakoudas
    显示剩余8条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接