Office Hours — Today, October 17

Thursday, October 15

Oct 17
3:50 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:05 PM
sudokai
has entered the room
Osama R.
has entered the room
4:10 PM
Mark M.
eek!
hello, sudokai and Osama!
sudokai
Hi!
Mark M.
sorry for any delays -- I got distracted, and the chat doesn't beep when people arrive
sudokai: you arrived first, so... how can I help you today?
sudokai
I was wondering
How can you keep your GPS sensor on
On Android
It seems that turning off the GPS itself
That process
Consumes a lot of energy
Mark M.
last I checked, you need to have an outstanding request for GPS fixes, typically from a running process
turning *off* GPS should not consume significant power
sudokai
And triggers the phone's power saving mechanism, killing the app process
Mark M.
when you say "turning off the GPS itself", do you mean disabling GPS in the Settings app?
or do you mean removing your request for location updates?
sudokai
View paste
> turning *off* GPS should not consume significant power

I know on good authority that it does
4:15 PM
Mark M.
again, how are you defining "turning off the GPS itself"?
sudokai
I'm using FusedLocation and I never remove the request for location updates
It's running in a foreground service as well
Mark M.
that is a strange definition for "turning off the GPS itself" -- I would describe that as turning on the GPS, insofar as the GPS radio will start to work to get location fixes
sudokai
The problem seems, at least to me, that the underlyng FusedLocation library decides to turn off the GPS
I got a logcat log about that event
Mark M.
which form of location updates are you using? a callback or a PendingIntent?
sudokai
immediately afterwards, the manufacturer's energy saver kicked in
PendingIntent
Do you know how FusedLocation works?
I was thinking maybe I could start a separate LocationManager request for location updates
Mark M.
in terms of its API, I haven't fussed with it too much in the past two years
sudokai
As a keepalive thing
Mark M.
well, why not just use the callback? if you have a foreground service, why would you use a PendingIntent?
sudokai
So even when FusedLocation tries something weird
The other request would keep the sensor on
4:20 PM
sudokai
I'm talking about an empty LocationManager callback, the code would serve no other purpose than to keep the sensor from turning itself off
Mark M.
I was referring to the fused location API, using a callback rather than a PendingIntent
sudokai
Yeah, it was like that when I joined the project
Mark M.
ah
my primary concern is that you might have the cause and effect inverted
you are assuming that the fused location API is doing something, and that triggers a manufacturer power saving mode
Osama R.
has left the room
Mark M.
it's also possible that the manufacturer is entering a power saving mode, and that is impacting the fused location API
sudokai
I mean, I don't remove the location request myself
Mark M.
sure, but if the manufacturer is forcing the device into a low-power mode, the fused location API may be just following along
sudokai
But in the logcat, you clearly see the timeline of events
First, the GPS is turned off
Then there's a power surge
And the manufacturer's energy saver kicks in
Poof, app killed
Mark M.
you're assuming that the manufacturer's Logcat entry for the energy saver mode is occurring at the beginning of its work
sudokai
Yeah, we never know for sure right?
Mark M.
there doesn't have to be a log entry for everything that happens
are you using a WakeLock?
sudokai
Yeah, I put that into the service
When I start the service I request a partial wakelock
4:25 PM
Mark M.
is your app on the battery optimization whitelist (the details of which will vary by manufacturer)?
sudokai
But it doesn't seem to work. I think you actually wrote a post about this
Mark M.
partial wakelocks have benefits, but not necessarily for hours, courtesy of Doze mode
sudokai
Mark M.
so you have a foreground activity and a foreground service and a wakelock, and a power-saving mode is still kicking in?
is the screen on at the time?
sudokai
View paste
> is your app on the battery optimization whitelist
No
I'm afraid to add the code to enable it
I read they could ban you
Mark M.
yeah I wrote about that too
for the short term, though, you might just want to do it manually and see what the impacts are on the app behavior
if it doesn't make an impact, then there's no sense in going down that path any further
sudokai
Tbh, I didn't quite understand that post of yours I linked
Yeah good idea
This part
Mark M.
well, it doesn't help that I linked to Google Plus post...
sudokai
View paste
> if the process with the foreground service also has the foreground activity, Doze mode takes over again.
So, do you mean that this only works for foreground services started when the app is in the background?
Mark M.
4:30 PM
sudokai
Ah, that is just BS
Mark M.
this is several years old, so I'm still coming up to speed on this material myself
sudokai
Especially with Android 11
When foreground services started in the background cannot request location updates
We actually talked about this a few weeks ago
And you filed an issue asking for clarification
Mark M.
(at least, I assume that's the one that you are referring to)
sudokai
Yeah exactly
I've bookmarked the issue
Tbh, FusedLocation has given me so many issues
I cannot recommend it
Mark M.
I haven't worked with it in some time, and then only really with an active screen (not fully background)
on the whole, I try to avoid pure background stuff anymore, to the greatest extent possible
sudokai
They straight up give you false coordinates, in the worse case, dozens of kilometers away (but with an accuracy of just a few meters)
LocationManager works
4:35 PM
Mark M.
I personally prefer LocationManager simply because I prefer using as few Google proprietary libraries as possible
so, if I were creating my own app, and for some inexplicable reason I needed location data, I would try to use LocationManager
sudokai
Yeah, I'm trying to migrate to LocationManager
Mark M.
anyway, the blog post that you linked to, and the issue it links to in turn, are not related to locations -- that's describing general wakelock behavior and a quirk that existed at least back in the Android 5.0 timeframe
sudokai
How do push notifications work with Doze
Mark M.
it used to be that high-priority FCM messages would break through Doze mode
sudokai
Do they wake your app or how does that work?
Mark M.
they set some limits on that back in Android 9 or so, IIRC
so, yeah, a high-priority FCM message would still get delivered to your app, despite Doze mode
(at least, they were supposed to -- I never wound up needing to try that)
sudokai
So if you want to perform some periodic work, let's say every 30s, I could send myself a push notification every 30s?
Mark M.
I suspect that FCM and/or newer versions of Android will not allow that frequent of a delivery of a high-priority message
4:40 PM
Mark M.
sudokai
Okay, I seem to recall that AlarmManager's minimum period was 1 minute right?
Mark M.
yes
from that link that I just posted: "Similarly, if the app doesn't show a notification upon receiving a high-priority FCM message, it won't give the user a chance to interact with the app and thus promote it to the active bucket. In fact, the only intended use for high-priority FCM messages is to push a notification to the user, so this situation should never occur. If you inappropriately mark an FCM message as high-priority when it doesn't trigger user interaction, it can cause other negative consequences; for example, it can result in your app exhausting its quota, causing genuinely urgent FCM messages to be treated as normal-priority. "
so, there's a quota
Osama R.
has entered the room
Osama R.
has left the room
sudokai
So, there's really no way to do something periodically in Android every 10s, let's say...
Mark M.
not indefinitely
at least not indefinitely without foreground UI
sudokai
Can you elaborate a bit?
Mark M.
you have a foreground service, so there is nothing stopping you from using a ScheduledExecutorService or Observable.timer() or whatever to get control every 10 seconds
and, initially, you will indeed get control every 10 second
but, eventually, the device will go to sleep... unless you have a wakelock
sudokai
Until?
Oh, okay
Mark M.
and then, how well and long that wakelock works gets managed by Doze mode, device manufacturer specific power hacks, etc.
sudokai
But you just wrote that wakelocks don't work when the app is in foreground
It's a nightmare
Mark M.
by "just", you mean five years ago
4:45 PM
sudokai
Yeah :D
4:45 PM
Mark M.
and, according to the issue that the blog post linked to, Google thinks they fixed it in Android 6.0
sudokai
Oh okay
Mark M.
I suspect that a lot of those follow-up comments are developers running into various problems with this background stuff and choosing to post on that issue as it kinda sorta looked like what they were experiencing
but, yes, background work on Android is a nightmare now
sudokai
I've encountered problems with WorkManager btw
Mark M.
what sort of problems?
sudokai
From time to time, a work request might be started twice
Mark M.
you mean, twice simultaneously?
sudokai
Or one immediately after the other
I'm not sure, I caught it by chance
when debugging
Mark M.
this is for periodic work?
sudokai
No, one time work
Mark M.
oh, well, that's bad
sudokai
And actually I think it was even an unique work
Which makes it even worse
Mark M.
agreed
sudokai
It doesn't happen very often
Mark M.
unfortunately, it's going to be one of those things where, without a reproducible test case, Google isn't likely to be able to do anything about it
sudokai
I've been able to reproduce it twice
Out of a lot of times
And I don't know what triggered it
4:50 PM
Mark M.
right, and I'm guessing that is in your real app, which you probably aren't just going to post as source code as an issue attachment :-)
4:50 PM
sudokai
Yeah
We got a lot of users
So all kinds of weird issues come up
Mark M.
Android is definitely "death by 1000 edge cases"
sudokai
Like, have you ever encountered a location update callback just not receiving anything?
For like 20 minutes
Mark M.
if location access is disabled in Settings, sure
sudokai
No no
Not disabled
Mark M.
or, if I'm in a parking garage, sure (speaking here as a user, not a developer)
sudokai
No, this was outdoors
Well, it could be bad GPS signal
Who knows
Mark M.
alien spacecraft was flying between you and a GPS satellite :-)
sudokai
I'm also not 100% sure WorkManager's network constraints work reliably
Mark M.
a lot of those constraints really just trickle down to JobScheduler
sudokai
I looked at the code, they register a broadcast receiver or network callback to receive the network info changes
I'm sure what they do wrong, if anything
Osama R.
has entered the room
sudokai
But weekly I receive reports from users
4:55 PM
Mark M.
let me take a question from Osama
4:55 PM
Mark M.
Osama: how can I help you today?
sudokai
Sure!
Osama R.
View paste (12 more lines)
Nothing huge I'm sure. 

fun main() {

    val myContext = Dispatchers.Default + SupervisorJob()
/*
    withContext(myContext) {
        println("This is executed before the delay")
        stallForTime()
        println("This is executed after the delay")
    }
*/

    GlobalScope.launch(Default  ) {
        println("some")
...
Why is "some" not getting printed. But once I uncomment the withContext part, some prints. Why?
Mark M.
if you are running this from the command line, your process might end before the dispatcher gets around to executing your coroutine
coroutines don't keep the JVM process around
Osama R.
I see. I had forgotten that. But then why does withContext work?
Mark M.
to be honest, I am not completely certain
I have not done a lot with this sort of scenario, running coroutines from the command line where coroutines might continue past my main() completion
Osama R.
I'm using intellij tho.
not android
but I guess intellij will run it on command line as wel
Mark M.
yeah, if this is just an ordinary Java/Kotlin app project, it's pretty much by definition a command-line program, unless you are tying into some GUI framework, Web environment, etc.
I have used coroutines from command-line Kotlin code, but I always have blocked to wait for the coroutines to end, using join()
Osama R.
I wonder if its due to structured concurrency changes made in kotlin
5:00 PM
Mark M.
it's also possible that your SupervisorJob has a role
Osama R.
I'm trying to re-write Klassbook examples into intellij. You don't think coroutine book would be outdated right now?
Mark M.
no, why would it?
Osama R.
removing SupervisorJob didn't change behavior
Mark M.
OK
Osama R.
I just can't think of why it doesn't work with only GlobalScope.
Mark M.
like I said, I have not played with this sort of scenario -- my coroutines work has been in Android, JavaScript, and command-line (but there only where I specifically ensure that my coroutines finish before the app exits)
Osama R.
hmm. How do I block the thread to ensure it works?
Mark M.
I call join() on my coroutines before main() returns
in your code snippet, launch() returns a Job -- call join() on it
5:05 PM
Mark M.
anyway, I do need to move along, and I am sorry that I did not get to you sooner -- you vanished before I had a chance!
so, that's a wrap for today's chat
sudokai
Thanks Mark!
Mark M.
the next one is Tuesday at 8:30am US Eastern
sudokai
Always great to hear your insights
Mark M.
thanks!
this chat's transcript will appear on https://commonsware.com/office-hours/ shortly
have a pleasant day!
sudokai
You too!
sudokai
has left the room
Osama R.
has left the room
Mark M.
turned off guest access

Thursday, October 15

 

Office Hours

People in this transcript

  • Mark Murphy
  • Osama Rao
  • sudokai