Office Hours — Today, November 21

Thursday, November 19

Nov 21
3:50 PM
Mark M.
has entered the room
Mark M.
turned on guest access
3:55 PM
Kai H.
has entered the room
4:00 PM
Mark M.
hello, Kai!
how can I help you today?
Kai H.
Hello Mark
Kotlin: When doing 'operator fun Point.unaryMinus() = {"test"}', I get a strange output. Can you please explain to me what I am doing there? :D
Mark M.
you are declaring the function to return a function type, in the form of a lambda expression
if you want it to return the string, remove the {} part
leaving you with operator fun Point.unaryMinus() = "test"
View paste
for example, I just ran this in the Klassbook's scratch pad:

operator fun String.unaryMinus() = "test"

fun main() {
  println(-"hello, world!")
}
and the output is: test
Kai H.
I could also use a function someting instead of the direct output, right?
4:05 PM
Kai H.
In the way of "operator fun String.unaryMinus() { ... }"
Mark M.
yes, you could have the body be { return "test" } and get rid of the =
Kai H.
'operator fun Point.unaryPlus() { return "test" }' gives me the error "Type mismatch: inferred type is String but Unit was expected"
I think im pretty confused by this "=" syntax and what is returned when.
Mark M.
oh, you also need to declare the return type in that case
View paste
operator fun String.unaryMinus(): String { return "test" }

fun main() {
  println(-"hello, world!")
}
Kai H.
That worked.
Mark M.
the "normal" syntax is that, where the function declares the return type and uses the return keyword
the = syntax is a shorthand
it basically says "the stuff to the right of the = is what is returned, and infer the return type based on the type of whatever that stuff-to-the-right is"
Kai H.
Ok
Mark M.
so, fun foo() = "test" returns a String
fun foo(): String { return "test" } also returns a String
fun foo() = { "test" } returns a lambda expression
Kai H.
So I'd have to do foo() to actually execute the lambda?
4:10 PM
Mark M.
well, foo() evaluates to the lambda expression, so foo()() should evaluate to "test"
Kai H.
damn
Mark M.
View paste
fun foo() = { "test" }

fun main() {
  println(foo())
  println(foo()())
}
in the Klassbook, the second println() prints: test
the first one prints some JavaScript source code for the lambda expression, basically
sudokai
has entered the room
Kai H.
That explains the strange output I was seeing
Hi Kai
sudokai
Hi!
Mark M.
Kai: let me take a question from sudokai, and I'll be with you again shortly
sudokai: hi! how can I help you today?
sudokai
Hi, is using a PendingIntent to communicate with a Service less efficient than starting the service yourself?
Mark M.
well, usually they solve separate problems -- you use a PendingIntent when you want something else to start the service (AlarmManager, a notification, etc.)
there is nothing stopping you from using a PendingIntent in your own code, and it's probably incrementally slower, but it's unlikely to be a performance problem
4:15 PM
sudokai
So, the backstory is: I'm using a PendingIntent with FusedLocationProvider.
The PendingIntent points to my Foreground Service. So each time a new GPS coordinate comes in, I get it inside the service's onStartCommand
Mark M.
OK, and FusedLocationProvider is starting your service from its own Play Services process
sudokai
Yeah and my app gets killed for using too much battery
I suppose what you say is what's happening
Mark M.
the benefit of that API is that your app does not need to be running when the location fix comes in -- Android will fork a fresh process for you
sudokai
Anyway, long story short, I've got a contact at a major phone manufacturer, and I got him to take a look at my app using their internal debugging tools
And he says that my Service is being started every 5 seconds
That's why the battery manager kicks in
And kills the app
I don't start the service myself explicitly
So I reached the conclusion that it must be FusedLocationProvider's doing
4:20 PM
sudokai
Does that make sense?
4:20 PM
sudokai
This is why I'm asking the question.
> "OK, and FusedLocationProvider is starting your service from its own Play Services process"
I suppose something wrong is going on there
Mark M.
the implication is that your LocationRequest supports delivering location fixes to you every 5 seconds
if you do not need location fixes that quickly, reconfigure the LocationRequest
but, if the LocationRequest wants fast location fixes, and the device is getting fast location fixes, you will get fast service starts
sudokai
Well, actually my LocationRequest is configured at location fixes every 1 second, but I know the system takes that as a suggestion rather than some hard constraint
Mark M.
yes, but if it is getting location fixes every 5 seconds, Play Services will happily start your service every 5 seconds
sudokai
Yeah
Mark M.
the fact that the device manufacturer has a battery manager issue with frequent service starts is a problem
sudokai
I suppose that's what's happening?
Mark M.
is this a foreground service?
sudokai
Yeah
With type set to location too in the manifest
Anyway, just needed some cross validation on this.
Mark M.
you might consider using separate fused location provider requests
have one with your PendingIntent for a slow update period
once your service starts, register one with a LocationListener callback for faster results, while your service is running
sudokai
I was considering starting the service manually myself
4:25 PM
sudokai
> once your service starts, register one with a LocationListener callback for faster results, while your service is running
Yeah, exactly this
Mark M.
if their battery manager is slamming you for frequent service starts, you'll need to switch your frequent location fixes to the LocationListener approach, one way or another
in principle, you could still use the PendingIntent variant to help get the service started, so long as you set a long interval, so the battery manager doesn't get cranky
sudokai
Yeah...
FusedLocationProvider has given me nothing but problems
Mark M.
it's been a couple of years since I played with these APIs, though, so there could be nuances that I'm missing
sudokai
I do not recommend using it haha
It lies and gives you false location kilometers away
From time to time
I reported it, they said they fixed it
But it's back again
Mark M.
yeah, I've heard complaints about it
let me take another question from Kai, and I will get back to you shortly
Kai: back to you! do you have another question?
Kai H.
Not right now
Mark M.
OK, if you come up with one, let me know!
in the meantime...
sudokai: back to you! assuming that you haven't moved kilometers away in the past minute... :-)
sudokai
Haha
Anyway, I'm moving to LocationManager
4:30 PM
sudokai
Mark, do you know anything about Firebase Cloud Messaging not working on some devices?
Mark M.
other than "it needs a device with Play Services", no, but I haven't used that in a couple of years either
sudokai
I was going to say that, I know this happens if the device doesn't have Google Play Services...but I've seen phones WITH Google Play Services that couldn't get a FCM token
It's a minority for sure, but it's there
Mark M.
couldn't get a token? that's surprising, since that's an outbound call
I would have expected the problem to be more of messages not getting delivered
sudokai
Right
I'm fortunate and unfortunate enough to have a large user base
And I see this issue in the crash reports
I suppose delivery is also an issue
But they can't even get a token
Mark M.
when you say "minority", is it small enough that it might be people might be messing with the app and doing something to affect your FirebaseMessagingService implementation?
or is it enough that this is unlikely to be script kiddies?
sudokai
It could be
But our userbase is not very computer savvy
4:35 PM
Mark M.
no, but script kiddies go after whatever they want to
sudokai
Okay, that makes sense
Yeah, it could be that
Mark M.
for example, my subscriber base doesn't have a reason to attack the Warescription site, but I had to add that CAPTCHA to deal with somebody doing automated registrations
sudokai
I saw your catpcha today!
Does it work well?
We got some russian hackers that bypassed our recaptcha set at maximum difficulty
Serious business :(
Mark M.
hCaptcha so far seems to be working OK, though it's tough to tell whether anyone is getting blocked and simply not reporting the problem to me
sudokai
Why hCaptcha and not recaptcha?
Mark M.
I wanted something non-Googly
Kai H.
I only attack the Office Hours by regularly being here ;-)
Mark M.
Kai: fortunately, 37 Signals has a beefy server farm :-)
Kai H.
But there is only one Mark
Murphy.
Mark M.
sudokai: also, I figured that since reCaptcha has such a huge market share, hCaptcha might not be getting as much "how do we break it" analysis
sudokai
I remembered another issue
Sorry I have so many questions
I usually miss the office hours
4:40 PM
Mark M.
go right ahead!
sudokai
So, I've been seeing some Android 4 phone crashing while loading a vector drawable I recently added
How's that possible?
I imported the SVG using Android Studio
New Vector Asset
Mark M.
I haven't dealt with Android 4.x in quite some time, but I thought they didn't use vector drawables, and you had to rig things up to generate PNGs for them
did they add a vector drawable backport?
if so, perhaps there's a bug in that library
sudokai
Mmm, I had no idea that they didn't support it
Like, I'm still quite inexperienced and we already have tons of vector drawables, so I assumed that they worked fine
Mark M.
presumably, you have something that is set up for them
perhaps there's something you need to do with this new one to get it to participate
sudokai
Okay, I'll look into it
Mark M.
sudokai
Thanks
4:45 PM
sudokai
One last thing: so I'm learning as I go and recently I had to do some activity and recyclerview animations
Mark M.
but, like I said, I haven't thought much about Android 4.x in years, so my recollections here are very rusty
sudokai
Do you still support Android 4?
We still support 4.2
Mark M.
personally? not in the second-generation books, and not in my current major client project
heck, my client's project has Android 7.0 as the minSdkVersion
sudokai
Which is your targetSdk then
minSdk sorry
oh wow
Mark M.
the second-generation books support back to 5.0
sudokai
That's amazing!
Yeah, all the other apps in our category support Android 5+ only
Mark M.
my client's users are reasonably likely to have modern phones -- there aren't very many even on 7.0
but, that's why minSdkVersion varies by app so much
different use cases have different needs
sudokai
True, our stats go as follows: 10 and 9 = 90% of the user base
10, 9, 8, 7 = 98% of the user base
But we got a lot of users, and even 0.5% are a lot
4:50 PM
sudokai
Anyway, so I mentioned animations and transitions and one thing I discovered is that the fade transition, that is, changing the alpha, seems to be very costly
So I had several transitions going on and I got rid of one fade transition and suddenly my animation stopped stuttering in old phones
Do you know any other "best practices" from your experience?
Mark M.
is there anything unusual about what was being transitioned (SurfaceView, TextureView, etc.)?
sudokai
Not really
It was an activity transition that animated the recyclewview elements too
Mark M.
it's possible that the older phones also have GPU limitations, and the animation support has steadily improved over the years
you may need to "gracefully degrade" on older devices and skip the transitions for those
sudokai
And each recyclerview element was a linearlayout with 2 elements inside
it was a grid
TIL about SurfaceView and TextureView
Wow
4:55 PM
Mark M.
yeah, SurfaceView in particular tended to be animation-resistant on older devices
they added TextureView to give us something that supported animations but also the same scenarios that SurfaceView supported (videos, maps, etc.)
then, later, they improved SurfaceView, such that TextureView was not really needed
I haven't checked what the current recommendations are for those, in terms of what to use for what Android versions
but, I know that the recommendations have changed over the years
sudokai
I haven't really worked with this advanced stuff yet
I'm the junior guy in our Android team and still learning as I go
Kai H.
You have a team. I'm envious
I am the team X)
sudokai
Well, it's a small team
How long have you been programming Android?
Kai H.
A bit over a year now
Still am a noob :D
sudokai
I started earlier this year
Kai H.
And know so little.
sudokai
Yeah, same
5:00 PM
sudokai
On paper I have 9 months of Android experience
Kai H.
Good thing we have Mark and his books and his office hours :)
Mark M.
I try to help!
sudokai
But half or more of that time was just figuring out algorithms and code
Kai H.
I have 15 or something.
You do!
sudokai
Things that had nothing to do with real Android
Yeah Mark
You are a life saver
Thanks
Mark M.
thanks for the kind words!
I almost hate to end the chat! :-)
but, it's that time
Kai H.
;-)
Mark M.
the next chat is *tomorrow*, same time: 4pm US Eastern
sudokai
Btw, I saw an event for tomorrow???
Yeah, so it's confirmed
Kai H.
How come?
Mark M.
yeah, I'm avoiding a major American holiday in the latter half of next week
Kai H.
Ok
Good to know.
sudokai
Thanksgiving
Mark M.
so the office hours schedule is a bit weird this coming week
right
Kai H.
Cu then :o
sudokai
What usually happens is that I miss the office hours
On the same day, I would tell myself
Okay today ask this
Kai H.
Alarm on your mobile?
sudokai
Then I have some other stuff come up
And when I remember, it's over
i subscribed to the calendar
I don't even remember where I found it
Mark M.
anyway, thanks for coming, and have a pleasant day!
Kai H.
When I really want to ask a question I put in an alarm
sudokai
Now I have a notification
Kai H.
But let's let Mark end it :D
sudokai
Okay
Thank you!
Kai H.
Same
Kai H.
has left the room
sudokai
has left the room
Mark M.
turned off guest access

Thursday, November 19

 

Office Hours

People in this transcript

  • Kai H.
  • Mark Murphy
  • sudokai