21

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?

android developer
  • 114,585
  • 152
  • 739
  • 1,270

2 Answers2

7

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.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
43matthew
  • 962
  • 8
  • 14
  • 1. It doesn't. Too bad about the requirement. 2. Yes, noticed it later. It's being connected. 3. I see. 4. When will it be published? How do you know this? What other features will be added? 5. JobScheduler allows this, but GcmNetworkManager doesn't. 6. Nice. Thank you. 7. Thing is, you need to track what was supposed to be scheduled, with which parameters (for example send-a-file will require to know which file, and to where). About your explanation, this still doesn't make sense, as it's done only for network-tasks. About old vs new tags, this is something to manage anyway, like DB changes. – android developer Jul 16 '15 at 06:41
  • 8. I meant that it could work like inexact alarms. The OS/framework should decide when to run each task, and they could do it in a batch. The algorithm already tries to run tasks in special conditions. a time condition is just an easy thing to check. I didn't mean that all tasks will run simultaneously , and I don't thing the algorithms does this so easily. 9. ok. 10. Do you know about this one too? Sometimes I need to tell the API "Do it now if possible, or later when you can" – android developer Jul 16 '15 at 06:44
  • 4. I worked on JobScheduler + GcmNetworkManager + SyncManager. 7. I see your point about send-a-file. Basically if you schedule a task and then your app upgrades the task won't run. This was not an issue so much before b/c of the limitations of the API (you could only provide a tag and were expected to stash any parameters you'd need locally, anyway). However given that you will be able to set a Bundle on the task this should be addressed. – 43matthew Jul 18 '15 at 01:26
  • 8. It is definitely possible to do, it wasn't done like this deliberately. The NetMgr tries to batch tasks together as much as possible if one client is scheduling things at 3pm every day there is a good chance that other client's executions will be batched along with, and lead to spiky server traffic. which is #10? – 43matthew Jul 18 '15 at 01:38
  • 4. Nice. So it will get published soon? I've also noticed that for JobScheduler I can run the task right away, yet GcmNetworkManager doesn't allow this, and it will run the task about 30-60 seconds since you told it to. 7. Why does it cancel only networks tasks (and at all) ? Also, how come the JobScheduler does have this behavior (or so it seems) ? 8. Will it also be added? 10. The first post has this question: "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?" – android developer Jul 18 '15 at 14:27
  • I've made a request to make the JobScheduler&GcmNetworkManager more feature complete, with less annoyances, and more similar to one another, here: https://code.google.com/p/android-developer-preview/issues/detail?id=2713 . Please cast your vote/opinion there, as I think those APIs should really be improved. – android developer Jul 19 '15 at 08:40
  • I think there is another issue with JobScheduler: Is it true that all Ids of the jobs need to be unique, even between very different classes that extend from JobService ? For example, if I have Job1 with id 0 and it works on JobService1 , I can't have Job2 with the same id on JobService2 ? – android developer Jul 19 '15 at 14:40
  • Let's move discussion to that post. Trying to make sense of this comment thread is difficult and unhelpful to others that may try to follow this conversation. Thanks for your feedback it is highly appreciated. – 43matthew Jul 20 '15 at 00:21
  • Thank you. And thank you for the attention. I don't think a lot of developers even got to use any of those APIs. – android developer Jul 20 '15 at 05:22
3

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.

filipproch
  • 725
  • 6
  • 15
  • 1. So extra code is needed in case it's not available. 2. ok, it needs RECEIVE_BOOT_COMPLETED permission. 3. ok, so default is CONNECTED . 4. I think you got it wrong. Both failure and success should schedule the task again. 5. That's too bad, as JobScheduler does have this feature. Also, it's wrong to put it in the Application class (or anywhere else) because you need to restore it even if the device has restarted, so you need to have a real storage method. 6. Sadly, again something only available on JobScheduler. 7. What will happen if I hold another WakeLock then? – android developer Jul 15 '15 at 12:00
  • 8. This is aweful, and for some reason it occurs only for network-tasks? 9. Too bad. 10. You can't check the state of the app, because the app was awakened by the play services. It's not in stopped state anymore. – android developer Jul 15 '15 at 12:01
  • @androiddeveloper 4. it works as i wrote it there, SUCCESS does not schedule the task again, I thing you have misunderstanding what this rescheduling is, it means that if your task fails, then it is added to queque again (no matter whether it is oneoff or repeat), if you pass success OneOff task realy shouldn't be rescheduled, Repeating tasks are repeated whatever you return, it doesn't affect this – filipproch Jul 15 '15 at 12:25
  • @androiddeveloper 5. not wrong to have Preferences loaded in Application class and have this stored in Preferences, which is how I meant it – filipproch Jul 15 '15 at 12:27
  • @androiddeveloper 7. I have no idea what happens then, you can try but as you have in docs that you shouldn't do it and rather make your own implementation it's your decision – filipproch Jul 15 '15 at 12:28
  • 4. the rescheduling that is caused by failure is set by "RESULT_FAILURE", "RESULT_RESCHEDULE" , but I asked what's the difference between failure and success, as both seem to have the same behavior. for both, the task is removed from the queue, and another is added if the task is periodic. About OneOff task, if it's reschedule vs not-reschedule, why do I need to have another possible option? 5. you pointed out it should be in the Application class, but it really doesn't matter, since the source of the data isn't from there, but from a real storage. For you, it's just a caching place... – android developer Jul 15 '15 at 13:04
  • 7. Since it's an internet task, I can't really know how long it will take. It's weird that they say "short" as Internet connection can be really slow. As I understand, I won't even get a callback for when it "gave up" – android developer Jul 15 '15 at 13:05
  • @androiddeveloper by myself, for now, no big difference between FAILURE and SUCCESS, the only one I know about is that when you use the command to print quequed tasks etc. there are statistics (FAILED / SUCCESS etc.). About the Application class, yeah you are right, I fixed it in the example on Github. About the time, internet connection can be slow, maybe Google will in future allow to overcome this somehow, but I think that most connections can fit in that time interval. If you are downloading large data, you can require WIFI connection while creating the task. – filipproch Jul 15 '15 at 13:13
  • 1
    I see. I should definitely tell Google about those missing and yet very important features. The least they could do is to have the same functionality as JobScheduler. Thank you for your time. – android developer Jul 15 '15 at 13:23
  • Say, I've noticed that if I try to schedule a OneoffTask that should start right away, it takes quite a long time till it decides to start. It took it almost a whole minute to be executed, from the time I've scheduled it. How come? – android developer Jul 15 '15 at 14:20
  • There's a minimum wait of 30 seconds according to the docs. "Note that you can request a one-off task to be executed at any point in the future, but to prevent abuse the scheduler will only set an alarm at a minimum of 30 seconds in the future. Your task can still be run earlier than this if some network event occurs to wake up the scheduler." – sakis kaliakoudas Nov 12 '15 at 02:26
  • My question is: when a periodic task is scheduled, is the first execution performed right away or after the setPeriod time? i.e. I set a periodic task every 6 hours. Does it start right away or is the first execution after 6 hours ? – sakis kaliakoudas Nov 12 '15 at 02:27
  • @sakiskaliakoudas the first execution is after the 6 hours – filipproch Nov 12 '15 at 09:57