Nov 21 | 3:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Nov 21 | 3:55 PM |
Kai H. | has entered the room |
Nov 21 | 4:00 PM |
Mark M. |
hello, Kai!
|
Mark M. |
how can I help you today?
|
Kai H. |
Hello Mark
|
Kai H. |
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
|
Mark M. |
if you want it to return the string, remove the {} part
|
Mark M. |
leaving you with operator fun Point.unaryMinus() = "test"
|
Mark M. |
View paste
|
Mark M. |
and the output is: test
|
Kai H. |
I could also use a function someting instead of the direct output, right?
|
Nov 21 | 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"
|
Kai H. |
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
|
Mark M. |
View paste
|
Kai H. |
That worked.
|
Mark M. |
the "normal" syntax is that, where the function declares the return type and uses the return keyword
|
Mark M. |
the = syntax is a shorthand
|
Mark M. |
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
|
Mark M. |
fun foo(): String { return "test" } also returns a String
|
Mark M. |
fun foo() = { "test" } returns a lambda expression
|
Kai H. |
So I'd have to do foo() to actually execute the lambda?
|
Nov 21 | 4:10 PM |
Mark M. |
well, foo() evaluates to the lambda expression, so foo()() should evaluate to "test"
|
Kai H. |
damn
|
Mark M. | |
Mark M. |
in the Klassbook, the second println() prints: test
|
Mark M. |
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
|
Kai H. |
Hi Kai
|
sudokai |
Hi!
|
Mark M. |
Kai: let me take a question from sudokai, and I'll be with you again shortly
|
Mark M. |
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.)
|
Mark M. |
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
|
Nov 21 | 4:15 PM |
sudokai |
So, the backstory is: I'm using a PendingIntent with FusedLocationProvider.
|
sudokai |
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 | |
sudokai |
Yeah and my app gets killed for using too much battery
|
sudokai |
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
|
sudokai |
And he says that my Service is being started every 5 seconds
|
sudokai |
That's why the battery manager kicks in
|
sudokai |
And kills the app
|
sudokai |
I don't start the service myself explicitly
|
sudokai |
So I reached the conclusion that it must be FusedLocationProvider's doing
|
Nov 21 | 4:20 PM |
sudokai |
Does that make sense?
|
Nov 21 | 4:20 PM |
sudokai |
This is why I'm asking the question.
|
sudokai |
> "OK, and FusedLocationProvider is starting your service from its own Play Services process"
|
sudokai |
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
|
Mark M. |
if you do not need location fixes that quickly, reconfigure the LocationRequest
|
Mark M. |
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
|
sudokai |
With type set to location too in the manifest
|
sudokai |
Anyway, just needed some cross validation on this.
|
Mark M. |
you might consider using separate fused location provider requests
|
Mark M. |
have one with your PendingIntent for a slow update period
|
Mark M. |
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
|
Nov 21 | 4:25 PM |
sudokai |
> once your service starts, register one with a LocationListener callback for faster results, while your service is running
|
sudokai |
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
|
Mark M. |
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...
|
sudokai |
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
|
sudokai |
It lies and gives you false location kilometers away
|
sudokai |
From time to time
|
sudokai |
I reported it, they said they fixed it
|
sudokai |
But it's back again
|
Mark M. |
yeah, I've heard complaints about it
|
Mark M. |
let me take another question from Kai, and I will get back to you shortly
|
Mark M. |
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!
|
Mark M. |
in the meantime...
|
Mark M. |
sudokai: back to you! assuming that you haven't moved kilometers away in the past minute... :-)
|
sudokai |
Haha
|
sudokai |
Anyway, I'm moving to LocationManager
|
Nov 21 | 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
|
sudokai |
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
|
Mark M. |
I would have expected the problem to be more of messages not getting delivered
|
sudokai |
Right
|
sudokai |
I'm fortunate and unfortunate enough to have a large user base
|
sudokai |
And I see this issue in the crash reports
|
sudokai |
I suppose delivery is also an issue
|
sudokai |
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?
|
Mark M. |
or is it enough that this is unlikely to be script kiddies?
|
sudokai |
It could be
|
sudokai |
But our userbase is not very computer savvy
|
Nov 21 | 4:35 PM |
Mark M. |
no, but script kiddies go after whatever they want to
|
sudokai |
Okay, that makes sense
|
sudokai |
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!
|
sudokai |
Does it work well?
|
sudokai |
We got some russian hackers that bypassed our recaptcha set at maximum difficulty
|
sudokai |
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
|
Kai H. |
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
|
sudokai |
Sorry I have so many questions
|
sudokai |
I usually miss the office hours
|
Nov 21 | 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
|
sudokai |
How's that possible?
|
sudokai |
I imported the SVG using Android Studio
|
sudokai |
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
|
Mark M. |
did they add a vector drawable backport?
|
Mark M. |
if so, perhaps there's a bug in that library
|
sudokai |
Mmm, I had no idea that they didn't support it
|
sudokai |
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
|
Mark M. |
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. |
OK, they did add a backport: https://developer.android.com/jetpack/androidx/...
|
sudokai |
Thanks
|
Nov 21 | 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?
|
sudokai |
We still support 4.2
|
Mark M. |
personally? not in the second-generation books, and not in my current major client project
|
Mark M. |
heck, my client's project has Android 7.0 as the minSdkVersion
|
sudokai |
Which is your targetSdk then
|
sudokai |
minSdk sorry
|
sudokai |
oh wow
|
Mark M. |
the second-generation books support back to 5.0
|
sudokai |
That's amazing!
|
sudokai |
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
|
Mark M. |
but, that's why minSdkVersion varies by app so much
|
Mark M. |
different use cases have different needs
|
sudokai |
True, our stats go as follows: 10 and 9 = 90% of the user base
|
sudokai |
10, 9, 8, 7 = 98% of the user base
|
sudokai |
But we got a lot of users, and even 0.5% are a lot
|
Nov 21 | 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
|
sudokai |
So I had several transitions going on and I got rid of one fade transition and suddenly my animation stopped stuttering in old phones
|
sudokai |
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
|
sudokai |
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
|
Mark M. |
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
|
sudokai |
it was a grid
|
sudokai |
TIL about SurfaceView and TextureView
|
sudokai |
Wow
|
Nov 21 | 4:55 PM |
Mark M. |
yeah, SurfaceView in particular tended to be animation-resistant on older devices
|
Mark M. |
they added TextureView to give us something that supported animations but also the same scenarios that SurfaceView supported (videos, maps, etc.)
|
Mark M. |
then, later, they improved SurfaceView, such that TextureView was not really needed
|
Mark M. |
I haven't checked what the current recommendations are for those, in terms of what to use for what Android versions
|
Mark M. |
but, I know that the recommendations have changed over the years
|
sudokai |
I haven't really worked with this advanced stuff yet
|
sudokai |
I'm the junior guy in our Android team and still learning as I go
|
Kai H. |
You have a team. I'm envious
|
Kai H. |
I am the team X)
|
sudokai |
Well, it's a small team
|
sudokai |
How long have you been programming Android?
|
Kai H. |
A bit over a year now
|
Kai H. |
Still am a noob :D
|
sudokai |
I started earlier this year
|
Kai H. |
And know so little.
|
sudokai |
Yeah, same
|
Nov 21 | 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.
|
Kai H. |
You do!
|
sudokai |
Things that had nothing to do with real Android
|
sudokai |
Yeah Mark
|
sudokai |
You are a life saver
|
sudokai |
Thanks
|
Mark M. |
thanks for the kind words!
|
Mark M. |
I almost hate to end the chat! :-)
|
Mark M. |
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???
|
sudokai |
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
|
Kai H. |
Good to know.
|
sudokai |
Thanksgiving
|
Mark M. |
so the office hours schedule is a bit weird this coming week
|
Mark M. |
right
|
Kai H. |
Cu then :o
|
sudokai |
What usually happens is that I miss the office hours
|
sudokai |
On the same day, I would tell myself
|
sudokai |
Okay today ask this
|
Kai H. |
Alarm on your mobile?
|
sudokai |
Then I have some other stuff come up
|
sudokai |
And when I remember, it's over
|
sudokai |
i subscribed to the calendar
|
sudokai |
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
|
sudokai |
Thank you!
|
Kai H. |
Same
|
Kai H. | has left the room |
sudokai | has left the room |
Mark M. | turned off guest access |