android – Some questions about GcmTaskService-ThrowExceptions

Exception or error:

Background

I wanted to use the new JobScheduler API that was presented on Lollipop, but sadly it doesn’t have an official port for pre-Lollipop.

However, there is the GcmTaskService, which provides very similar functionalities.

The problem

This API is quite new, so there are very few places to look for information of how to use it (here and here, for example).

The questions

I have a few questions about this new API :

  1. It seems that it requires Google Play Services (here) to be used (except for when using Lollipop version of Android, which will use the normal JobScheduler). What should I do in case the Google play services aren’t available?

  2. It seems that even though I’ve used “setPersisted(true)” for a repeated task, when I restart the device the task won’t be called again. How come?
    EDIT: that’s because I missed a permission of RECEIVE_BOOT_COMPLETED .

  3. What is the default behavior of a task, in case I don’t use “setRequiredNetwork” ? Is it “NETWORK_STATE_ANY” ?

  4. The docs say about what’s returned from onRunTask , I can return any of the values “RESULT_FAILURE”, “RESULT_RESCHEDULE”, “RESULT_SUCCESS” (info here). It seems both the FAILURE and SUCCESS options will do the same thing – remove the task from the queue. Is it true? If so, what exactly is the difference between them ? Do they function differently?

  5. Are “TaskParams” used only for the tag of the task? Can I somehow pass a bundle to the task using the API? Otherwise, I would need to set a DB for storing what should be passed to the tasks, right?

  6. Is it possible for the app to get the queue of the tasks? I know it’s possible using adb, but is it possible using the API too?

  7. They say (here) that each task has a wakelock of up to 3 minutes. What should be done if the task needs more than that? Should it acquire another wakelock for itself? Will the API warn that the wakelock was released? Here’s what the docs say:

The scheduler will hold a PowerManager.WakeLock for your service,
however after three minutes of execution if your task has not returned
it will be considered to have timed out, and the wakelock will be
released. Rescheduling your task at this point will have no effect. If
you suspect your task will run longer than this you should start your
own service explicitly or use some other mechanism; this API is
intended for relatively quick network operations.

  1. They say (here) that all networks-tasks are removed each time the app gets upgraded/replaced, and there is a call for “onInitializeTasks” when this happens, and that you can re-schedule them again. How can I re-schedule the tasks? I don’t think I can even get the list of tasks…

  2. Is it possible to tell the task to prefer specific times during the day ? For example, between the 14:00-15:00 ?

  3. I’ve noticed that if you schedule a task, and then you force-stop and/or clear data of the app, the task will still run. How can I avoid this behavior?

How to solve:

you can find answers to most of your questions it here.

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

To answers that are not answered there

7: You won’t get notified when wakelock is removed, and as they say in documentation, this API is only for short tasks, if you have longer, write your own implementation

9: No you can’t as of now, the API doesn’t allow it

10: That’s because Google Play services are taking care of it, and there is no way around it. You have to detect in the service whether the app is setup (I expect that’s your problem) eg. configuration is created etc. and eventually cancel all tasks when one of them is called.

###

jacktech24 did a really good job, but i will try as well in case there are any lingering questions.

  1. It seems that it requires Google Play Services (here) to be used (except for when using Lollipop version of Android, which will use the normal JobScheduler). What should I do in case the Google play services aren’t available?*

    You can’t use this API if Google Play Services isn’t available. Rather, the Google Play Services client library is designed to request that the user download and install Google Play Services if it detects that it’s missing, but I don’t believe that the GcmNetworkManager does this.

  2. What is the default behavior of a task, in case I don’t use “setRequiredNetwork” ? Is it “NETWORK_STATE_ANY” ?*

    The javadoc describes which is the default.

  3. The docs say about what’s returned from onRunTask , I can return any of the values “RESULT_FAILURE”, “RESULT_RESCHEDULE”, “RESULT_SUCCESS” (info here). It seems both the FAILURE and SUCCESS options will do the same thing – remove the task from the queue. Is it true? If so, what exactly is the difference between them ? Do they function differently?*

    The only difference between these 2 is that in the adb shell dumpsys it will display what you returned, so you can use this to troubleshoot issues.
    The other reason is that if the task fails, it is strange to require the client return a “success.”

  4. Are “TaskParams” used only for the tag of the task? Can I somehow pass a bundle to the task using the API? Otherwise, I would need to set a DB for storing what should be passed to the tasks, right?*

    In the next version of GmsCore the ability to add a bundle to the task should be supported.

  5. Is it possible for the app to get the queue of the tasks? I know it’s possible using adb, but is it possible using the API too?

    No it’s not possible. Instead you should perform the cancel when you want it and if the task is not there it will be a no-op. Similarly you should schedule the task at the point in your code where you would have queried for the list of tasks. use setUpdateCurrent=false to ensure that it doesn’t update the pre-existing task. The AlarmManager works in a similar way in that you would set the alarm regardless of whether the alarm was already set – the api was designed to follow this.

  6. They say (here) that each task has a wakelock of up to 3 minutes. What should be done if the task needs more than that? Should it acquire another wakelock for itself? Will the API warn that the wakelock was released? Here’s what the docs say:*

    Yes, the app should acquire its own wakelock and everything will be fine. The reason the scheduler releases the wakelock after 3 mins is because in practice having an unlimited wakelock timeout only leads to really hard to track down battery drain bugs. If you need longer than 3 mins you have a sophisticated enough use-case that you can dig into how the PowerManager APIs work and call the acquire()/release() yourself (it’s really quite simple, the fact that the network manager does it for you is more of a politeness than anything else).

  7. They say (here) that all networks-tasks are removed each time the app gets upgraded/replaced, and there is a call for “onInitializeTasks” when this happens, and that you can re-schedule them again. How can I re-schedule the tasks? I don’t think I can even get the list of tasks…*

    You reschedule the tasks the same way you scheduled them in the first place. Whatever function you used to schedule them, call that function from GcmTaskService#onInitializeTasks. This was done to avoid lingering tasks across app logic changes. Consider the situation where a developer changes their task timetable, and starts using a different tag. They would be required to call cancel(old_tag) after they’d detected the upgrade (which they’d have to add more code to do), which would mean they’d need a reference to the old (unused) tag even in their new code. This would imply that a tag is a stable identifier that shouldn’t change across app upgrades – which shouldn’t be a requirement for this api.

  8. Is it possible to tell the task to prefer specific times during the day ? For example, between the 14:00-15:00 ?*

    No, this type of background scheduling causes all sorts of problems with herding across large populations of devices. I.e. if 1 device runs a job at 15:00 that is probably fine. But if 1x10e6 do suddenly your server is in serious problems.

  9. I’ve noticed that if you schedule a task, and then you force-stop and/or clear data of the app, the task will still run. How can I avoid this behavior?*

    Unfortunately you can’t, but this is not intentional and should be changed – there should be no way for an app to run after the user has explicitly stopped it.

Leave a Reply

Your email address will not be published. Required fields are marked *