Office Hours — Today, January 15

Saturday, January 12

Jan 15
8:55 AM
Mark M.
has entered the room
Mark M.
turned on guest access
Kris E.
has entered the room
Kris E.
Hello Mark, I was hoping you could help me with a JobScheduler issue I am having.
Mark M.
I can try!
9:00 AM
Kris E.
So, after updating to Oreo I had to switch from AlarmManager to JobScheduler to do background updating of GPS, and the timing for JobScheduler firing is not very consistent. If the device is active it does fire around every 15 minutes but if the device is idle on modern versons of the OS (N+) it can be up to 3 hours between events.
Mark M.
yes, that's the effect of Doze mode
Kris E.
I was wonder if there was any best practices in setting up the job through the builder, or any settings that can be set to make it more like 15 minutes and not 3 hours which my client is not pleased with.
Mark M.
um, well, not really
users of the app can opt out of battery optimization for the app, which should help
but otherwise the limits on background work are what they are
Kris E.
So is the only way to force updates on a regular schedule using FCM?
Mark M.
technically, on Android 9.0+, even that might not work, depending on where the app is in the "bucket" system
but FCM at least can help
Kris E.
Is there any way to check (or prompt the user) to opt out of battery optimization?
Mark M.
if your app holds the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission, you can use ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS to ask the user to opt out of battery optimization
however, at least in 2015, this might get you banned from the Play Store: https://commonsware.com/blog/2015/11/11/google-...
Kris E.
And I guess that switching to WorkManager isn't going to make a difference then...
Mark M.
no, because in the end, it uses JobScheduler, at least on versions of Android that have it
9:05 AM
Mark M.
in the end, right now, background work in Android is not very reliable, let alone frequent, from the end user's standpoint
OTOH, battery life has dramatically improved
Kris E.
Right, so really (this is for a customer who wants to keep track of where workers deliveries are) the only solution is compile against 7 and not have the app distributed in the App Store or force them to keep the app open. I am assuming that if the device is moving there will be more frequent updates, but if the device stays in one place and not active then it won't wake up.
Mark M.
if the device is moving, full Doze mode does not kick in
that is mostly for "the user is asleep and the device is sitting on the nightstand" scenario
Kris E.
Yeah, and that is what my testing is showing, but in the field, even with the device moving it can be 30-45 minutes between updates. OK, thanks so much for your help, I just wanted to make sure that I was giving the most accurate information to client as possible. Thanks also for the books, they are invaluable -- my only regret is that I was developing on Android for 4 years before I found them.
9:10 AM
Mark M.
now that I check the release notes, it looks like jobs get deferred in partial Doze mode on Android 7.0+ -- see https://developer.android.com/about/versions/no...
AlarmManager alarms seem like they will work in partial Doze mode, though
and thanks for the kind words!
Kris E.
In 7 alarmManager works, in 8 it crashes if the app isn't foreground.
Mark M.
that may be a matter of what sort of PendingIntent you are using
on Android 8.0+, use PendingIntent.getForegroundService(), and have the service call startForeground() right away
Kris E.
Is that allowed? I thought would lead to Play store issues for sure.
Mark M.
no, foreground services are Google's recommended approach
*users* might not like them, as they clutter up the status bar
in your case, my guess is that users don't really have much choice about whether to use the app
9:15 AM
Kris E.
So my old solution used a broadcastReceiver, how do I switch that to a pending intent?
Mark M.
AlarmManager uses PendingIntent
if you are using PendingIntent.getBroadcast() to create that PendingIntent, that is fine
however, your receiver would need to either use JobIntentService (and then run risks with respect to JobManager) or a foreground service to get the work done
and on Android 8.0+, to start a foreground service, call startForegroundService() instead of startService() (plus have the service call startForeground())
Kris E.
OK, so in the onReceive I call PendingIntent.getForegroundService() and startForeground...
Mark M.
if you are using AlarmManager, and you want that alarm to trigger a broadcast receiver, the PendingIntent you use with AlarmManager would be created using PendingIntent.getBroadcast(), pointing to that receiver
alternatively, you can have AlarmManager directly invoke your service -- *then* you would use PendingIntent.getForegroundService() on Android 8.0+
9:20 AM
Kris E.
OK, I'll give that a shot. Thanks so much...
Mark M.
you're welcome!
Kris E.
has left the room
Kris E.
has entered the room
9:40 AM
Kris E.
has left the room
10:00 AM
Mark M.
turned off guest access

Saturday, January 12

 

Office Hours

People in this transcript

  • Kris Erickson
  • Mark Murphy