JobScheduler, Job IDs, and Libraries
TL;DR: If you write an Android library, and it uses JobScheduler
to schedule
jobs, make sure that the job IDs that you use are configurable by the app that
is using your library.
Ori Wasserman asked a damn good question this morning (my time) on Stack Overflow:
According to the documentation, jobs must have a unique Job ID per uid. If I use a 3rd party library which also schedules jobs, does this mean I can’t use the same Job ID as theirs? If so, how can I avoid these kind of collisions?
(“aw, crap” moments like this are better than caffeine for waking me up…)
When you create a JobInfo
via a JobInfo.Builder
, you provide an int
that serves as a unique ID for that job within all apps associated with your
Linux user ID. For most developers, that means that the ID is unique within
your app. The “associated with your Linux user ID” part is for developers
who are using android:sharedUserId
, which I sincerely hope is not being used
all that much outside of custom ROM developers.
However, since that ID is unique for the app, that would include being unique across both the app’s own code and the code from any library that the app uses. And that’s where the problem arises. I cannot see a good way to have everybody coordinate as to what the IDs are. And even if there is such a way, there is no requirement for all libraries to use that coordination point.
For example, you might think that we could use the id
resource trick: define
a custom id
resource for the job ID, and that id
value is guaranteed to be
unique within the resource identifier space. However:
-
The docs point out that the
id
needs to be stable across app updates, and therefore anid
resource is unsuitable -
There is nothing forcing library authors to use an
id
resource, anyway
If you are writing a library, while you are welcome to default the job IDs to
something (to simplify integration of your library), be sure to have some means
to allow the app to change those IDs. App developers, in turn, need to look
for library APIs related to job IDs and use them, if you are also using JobScheduler
elsewhere (in your app code or via yet more libraries).
As problems go, this one is not unique (pun intended). We also need unique int
values for Notification
IDs, for example. Similarly, if your library raises a
Notification
, while you might default your notification ID to some value, be
sure to allow app developers to change that value to something else, to avoid conflicts
with other notification IDs used elsewhere in the app.
Historically, the JobScheduler
job ID issue was not a big deal. Partially,
that is because JobScheduler
is new to Android 5.0, and only recently has
Android 5.0+ gotten to over 50% market share. Partially, that is because
only so many apps and libraries needed to schedule jobs.
However, with the continued War on Background Processing by way of Android O,
JobScheduler
becomes increasingly important:
-
You may find yourself using a job instead of an
IntentService
for background work that might take more than a minute, but less than ten minutes, and for which you would prefer not to use a foreground service -
JobScheduler
has been touted as an alternative to implicit broadcasts, though in truth that only works in a few cases
I half expect O Developer Preview 3 to show how JobScheduler
can be used
both as a floor wax and as a dessert topping.
Regardless, the number of libraries needing JobScheduler
should climb steadily,
and with that comes the issue of job ID conflicts.
In general, anywhere in Android that requires some sort of app-defined unique identifier, library developers should consider offering control over those identifiers to the consumers of the library.