paint-brush
WTF, Android SDK? → Part III: Geocoder aphasiaby@sebastian212000
2,702 reads
2,702 reads

WTF, Android SDK? → Part III: Geocoder aphasia

by Antonis TsagarisAugust 17th, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

So, here’s the deal: you want to get a human-readable address for a set of coordinates (latitude & longitude) you just retrieved using either the LocationManager API or the FusedLocation API.

Company Mentioned

Mention Thumbnail
featured image - WTF, Android SDK? → Part III: Geocoder aphasia
Antonis Tsagaris HackerNoon profile picture

Or how it stops working and there’s nothing you can do about it

So, here’s the deal: you want to get a human-readable address for a set of coordinates (latitude & longitude) you just retrieved using either the LocationManager API or the FusedLocation API.

A kind-hearted stranger on Stack Overflow… yeah, nope — a complete and utter dickhole on Stack Overflow lets slip that you should use Android’s Geocoder API before editing, locking and then deleting your post in an amazing display of Neckbeard Power, Fuck Yeah.

Unfazed, you Google “Geocoder” and decide to use that to get an address for your coordinates. Soon, you discover that Geocoder has a method called getFromLocation(), which returns a list of addresses for a set of coordinates. Exactly what the doctor ordered!


List<Address> addresses = new ArrayList<Address>();Geocoder geocoder = new Geocoder(this, Locale.getDefault());



try {addresses = geocoder.getFromLocation(latitude, longitude, 1);} catch (IOException e) {

     e.printStackTrace(); 

}

The third argument you pass in getFromLocation() is the maximum number of results you wish to get, one (1) in this case.

You let the method do its job (warning: this requires an internet connection and it happens on the UI thread, you have been warned) and if you’re lucky, as soon as it returns you get a List<Address> with one result. You then extract the address from the Address object



String city = “unknown location”;String country = “unknown location”;String address = “unknown address”;

try {

 city = addresses.get(0).getAddressLine(1);   
 country = addresses.get(0).getAddressLine(2);   
 address = addresses.get(0).getAddressLine(0); 

} catch (Exception e) { 

 city = “unknown location”;   
 country = “unknown location”;   
 address = “unknown address”; 

}

Sometimes, you’ll get a null value as a result when calling the getAddressLine() methods, so you’ll have to do the usual due diligence.

So far, so good. Nothing you haven’t seen before. Now, let me quote something from Geocoder’s official documentation

The Geocoder class requires a backend service that is not included in the core android framework.

This makes a lot of sense (although they forgot to capitalize “Android”, which caused my IBS to flare up again) since the lookup will naturally occur online.

Now, I challenge you to go on Geocoder’s documentation page and find anything mentioned about limits for the number of calls you can make to Geocoder’s backend service. Go on, I dare you.

Spoiler alert: you’ll find nothing. There’s no mention of this fact anywhere in the official documentation.

This is no joke. After a certain number of calls to the Geocoder backend service (or a certain frequency of calls or whatever — that’s the point: nobody knows), the returned Address object will contain null for every address line.

You won’t get any warning about this in the logcat. You won’t get an email that lets you know that you’ve gone over some limit and you certainly won’t get a Google engineer calling you to make sure you’re alright and if you’d like some tea.

Nope, your app will go from looking like this

…to looking like this

That is, if you’ve dealt with the null values gracefully. If you haven’t, good luck explaining what NPEs are to your irate users.

Eagle-eyed readers may have noticed that the two screenshots are from different devices: one is from a 2013 Moto G and the other is from the Pixel XL, respectively. Both were taken minutes apart, on the same Wi-Fi network, which seemed to suggest that the limits on the Geocoder calls are on a per-device basis.

After searching the web, I came across this Stack Overflow question (sorry I was so hard on you earlier, SO, it’s because I love you). After someone contacted Developer Support about this, this is what Google support had to say on the matter

This API is designed for reasonable use by client applications. It is actively monitored for abuse (e.g. requests per second), but you should not have any issues with the use case you have described.

I don’t want to sound like a whiny baby but does Developer Support at Google actually think that “reasonable use” is a reasonable answer? And what specifically constitutes abuse?

Shouldn’t this kind of thing be mentioned in the class documentation?

This could literally turn your app into a crashy mess in an instant but you get no mention of limits, no mention of abuse and no mention of your calls being monitored anywhere in the documentation. Instead, you simply get blocked from getting any useful data without any warning.

WTF, Android SDK?