Office Hours — Today, January 19

Thursday, January 17

Jan 19
3:55 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:10 PM
Paul R.
has entered the room
Paul R.
Greetings Mark
I have two questions today.
Mark M.
hello, Paul!
fire away!
Paul R.
First up: tell me about securely using an API key in an Android app. Is it possible to achieve near perfect security?
Mark M.
yes: by not putting the API key in the Android app
otherwise, no
Paul R.
Let's drill into that.
Mark M.
for example, if the API in question is something that you could actually execute from your Web service, perhaps you do that, with your app calling your Web service
4:15 PM
Paul R.
How do I ensure that the web service knows it is my app?
Mark M.
well, to an extent, you might not strictly care
what matters is whether the user who is accessing your Web service is your user or not
now, if your Web service does not involve users with accounts, then you have a problem
your Web service is a publicly accessible API, like it or not, even though it may be an undocumented and unsupported API
Paul R.
My concern is that given an APK, a hacker can figure out how to access the web service. Then the hacker need only replicate that from another app to exploit the web service.
Mark M.
sure
Paul R.
How do I prevent this from happening?
Mark M.
stop programming computers, I guess
I mean, if you are making the endpoint publicly accessible, there is no "publicly accessible only from a certain piece of client software"
simply because bits on the wire have no provenance, proving that they came from a certain piece of client software
4:20 PM
Mark M.
that's why I asked if your Web service is tied to users and accounts
if it is, then the primary "defense" is "you have to have a valid account"
and from there, whether the client is yours or some third party's ideally should not matter
Paul R.
Yes, as long as the web service verifies the User, that makes sense.
Mark M.
obfuscation of various forms (ProGuard/DexGuard-style tools, NDK, etc.) can slow down somebody cloning an app or extracting an API key, but it can't stop them
initially, when your app has no users, nobody will bother attacking the app or its Web service, because there may be no perceived value
Paul R.
I'll be back in a minute with my second question. You did good with the first.
4:25 PM
Paul R.
ok, second issue is streaming. With either Kotlin (preferred) or Java, how would you sketch out reading a large (many megabytes) gz file containing lines of JSON data such that the parsing can be done a line at a time without having to read in the whole batch of lines?
Mark M.
JSON isn't a great format for this
you can't strictly parse JSON without having the entire thing in memory
Paul R.
Might be, but I have no control over that.
Mark M.
or, at least, access to the entire thing by the time that you're done
Paul R.
I can definitely parse a line at a time.
The whole file is not aJSON object, but each line is.
Mark M.
ah
that's a rather strange data structure
but, anyway, there are Gzip classes in the Android SDK
4:30 PM
Mark M.
so, you should be able to get a GZIPInputStream wrapped around a FileInputStream (with perhaps a BufferedInputStream in there somewhere)
then, wrap that in an InputStreamReader
then use forEachLine() in Kotlin
Paul R.
View paste
Here's the code currently: actual fun fetchLines(url: String): List<String> = URL(url).openConnection().apply {
    readTimeout = 800
    connectTimeout = 200
}.getInputStream().use {
    val gzStream = GZIPInputStream(it)
    val decoder = InputStreamReader(gzStream, "UTF-8")
    decoder.readLines()
}
Mark M.
switch readLines() to forEachLine() for line-by-line processing
so, decoder.forEachLine { line -> TODO() }
Paul R.
That simple? That's awesome.
Mark M.
lotsa nice extension functions in Kotlin!
now, I have no idea what the underlying implementation is and whether you'll run into some memory problem
but, in principle, this should work
also, you might consider val decoder = gzStream.bufferedReader("UTF-8"), to get buffering in there
(and since UTF-8 is the default for bufferedReader(), gzStream.bufferedReader() is probably sufficient)
4:35 PM
Paul R.
Very cool. Last question. I just re-upped my CommonsWare subscription that lapsed last november. Have you added much since then for Kotlin?
Mark M.
well, there's Elements of Kotlin 0.1 as a partial implementation of an intro guide to the language
Paul R.
A separate book?
Mark M.
yes
Paul R.
Good idea.
Mark M.
that explains a bit of what the future holds
Paul R.
I'll check it out. As always you've been very helpful. Thank you.
Mark M.
during the timeframe of your subscription, you'll get a complete Elements of Kotlin, a complete Elements of Android Jetpack (intro guide to Android, dual Java/Kotlin examples), and a rewritten Exploring Android (step-by-step tutorials, Kotlin/Jetpack)
plus some other new stuff
(e.g., Elements of Android Q, presumably)
and thanks for the kind words!
Paul R.
No problem. Talk to you soon.
Paul R.
has left the room
4:55 PM
Mark M.
turned off guest access

Thursday, January 17

 

Office Hours

People in this transcript

  • Mark Murphy
  • Paul Reilly