GcmTaskService 运行 可以异步任务吗?

Can GcmTaskService run async tasks?

我需要 运行 在 Android 应用程序的后台定期执行网络任务。

我最初打算使用 AlarmManager(不能使用 JobScheduler 因为它必须在棒棒糖之前的设备上工作),但后来我遇到了 GcmNetworkManager 这似乎更容易使用并提供更简单的 API,并且如果设备连接到互联网,它会处理 运行ning 任务(也不需要使用广播接收器,所以更少classes 维护)。

我遇到的问题是我需要 运行 的任务由 3 个异步步骤组成,GcmTaskService 似乎是为 运行 同步任务创建的。

我已经对此进行了测试,发现我的异步任务 运行 在 GcmTaskService 中结束之前都很好(我的服务然后自行停止),但是我担心这可能是更多的是巧合,因为我的异步任务非常快,而不是服务没有在 GcmTaskService 代码中停止的事实(我试图查看代码,但它被混淆了所以很难理解它是什么确实)。

有谁知道 GcmTaskService 实际上是 运行 直到扩展 class 停止它或者它是否会在同步任务结束时停止?

GcmTaskService只运行你的任务3分钟,3分钟后算超时。因此,如果您有大型任务,我建议您创建自己的服务。
关于 GcmTaskService 的更多信息:read this

经过一些调查和调试,我找到了答案。我会在这里描述它,以便将来它可以帮助其他人。

正如我所怀疑的那样,当 运行 需要的所有任务都完成时,GcmTaskService 会自行停止(这很有意义)。对此的证明是在这个方法上(在 GcmTaskService class 内):

private void zzdJ(String var1) {
    Set var2 = this.zzaIU;
    synchronized(this.zzaIU) {
        this.zzaIU.remove(var1);
        if(this.zzaIU.size() == 0) {
            this.stopSelf(this.zzaIV);
        }

    }
}

此方法在任务完成后(a.k.a。在 onRunTask() returns 之后从 运行 执行任务的线程调用。

var1是开发者在创建任务时分配给任务的标签,zzaIU是这个服务需要运行的任务列表。因此,正如我们所见,已完成的任务已从列表中删除,如果没有更多任务需要 运行,则服务将停止。

可能的解决方案:

但是 GcmTaskService 中的 运行 异步任务有一个可能的解决方案。为此,我们需要覆盖 onStartCommand() 方法,以防止 GcmTaskService 在另一个线程中启动任务。

代码将如下所示:

private boolean taskRunning = false;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    String intentAction = intent.getAction();
    if (SERVICE_ACTION_EXECUTE_TASK.equals(intentAction)) {
        taskRunning = true;

        // Run your async tasks. Make sure to stop the service when they end.
    } else if (SERVICE_ACTION_INITIALIZE.equals(intentAction)) {
        // Initialize tasks if needed (most likely not needed if they are running asynchronously)

        // If this step is not needed, make sure to stop the service if the tasks already run (this could be called after 
        // the service run all the tasks, and if we don't stop the service it'll stay running on the background without doing 
        // anything)
        if (!taskRunning) {
            stopSelf();
        }
    }

    return START_NOT_STICKY;
}


@Override
public int onRunTask(TaskParams taskParams) {
    // IMPORTANT: This method will not be run, since we have overridden the onStartCommand() to handle the tasks run ourselves,
    // which was needed because our tasks are asynchronous

    return GcmNetworkManager.RESULT_SUCCESS;
}

这仅在服务开发为 运行 1 个任务时有效,如果需要 运行 多个任务,您需要使用列表而不是 taskRunning 布尔值,并检查大小以查看在停止服务之前是否需要更多任务 运行(就像原始 GcmTaskService 代码那样)。

尽管这是一个解决方案,但它不是面向未来的,因为 GcmTaskService 上的代码可能会在未来的 Google Play 服务版本中发生根本性变化,在这种情况下,它可能会破坏此功能(不太可能,但可能)。所以我想我会选择 AlarmManager 而不是为了安全起见。

从 TaskService 的 onRunTask 启动您自己的服务如何? 蹩脚,但可能是最安全的......或者?