Android: Reverse geocoding - getFromLocation
Asked Answered
P

7

55

I am trying to get an address based on the long/lat. it appears that something like this should work?

Geocoder myLocation = Geocoder(Locale.getDefault());
    List myList = myLocation.getFromLocation(latPoint,lngPoint,1);

The issue is that I keep getting : The method Geocoder(Locale) is undefined for the type savemaplocation

Any assistance would be helpful. Thank you.


Thanks, I tried the context, locale one first, and that failed and was looking at some of the other constructors (I had seen one that had mentioned just locale). Regardless,

It did not work, as I am still getting : The method Geocoder(Context, Locale) is undefined for the type savemaplocation

I do have : import android.location.Geocoder;

Pottery answered 23/1, 2009 at 9:8 Comment(0)
M
70

The following code snippet is doing it for me (lat and lng are doubles declared above this bit):

Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
Morell answered 25/1, 2009 at 0:58 Comment(6)
I also tried this, each time I try to view the address list, it bombs out. Not sure what is going on. I will try with a new app here in a day or two to see what I can find.Pottery
I found this very helpful for positioning stuff: blogoscoped.com/archive/2008-12-15-n14.htmlMorell
...also I've got the following two permissions in my manifest: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> When I missed one of them out (can't remember which one) the app threw a really unhelpful error.Morell
How can i add an api key to this class? So i can get more requests?Leukorrhea
Is it better to use Locale.US? As sometimes the getDefault() will return some issues, such as addresses in random language, no?Whitecollar
Do we have in the 2019 year (api>= 26 SDK) some way to get an address without passing the Context?Idaliaidalina
S
51

Here is a full example code using a Thread and a Handler to get the Geocoder answer without blocking the UI.

Geocoder call procedure, can be located in a Helper class

public static void getAddressFromLocation(
        final Location location, final Context context, final Handler handler) {
    Thread thread = new Thread() {
        @Override public void run() {
            Geocoder geocoder = new Geocoder(context, Locale.getDefault());   
            String result = null;
            try {
                List<Address> list = geocoder.getFromLocation(
                        location.getLatitude(), location.getLongitude(), 1);
                if (list != null && list.size() > 0) {
                    Address address = list.get(0);
                    // sending back first address line and locality
                    result = address.getAddressLine(0) + ", " + address.getLocality();
                }
            } catch (IOException e) {
                Log.e(TAG, "Impossible to connect to Geocoder", e);
            } finally {
                Message msg = Message.obtain();
                msg.setTarget(handler);
                if (result != null) {
                    msg.what = 1;
                    Bundle bundle = new Bundle();
                    bundle.putString("address", result);
                    msg.setData(bundle);
                } else 
                    msg.what = 0;
                msg.sendToTarget();
            }
        }
    };
    thread.start();
}

Here is the call to this Geocoder procedure in your UI Activity:

getAddressFromLocation(mLastKownLocation, this, new GeocoderHandler());

And the handler to show the results in your UI:

private class GeocoderHandler extends Handler {
    @Override
    public void handleMessage(Message message) {
        String result;
        switch (message.what) {
        case 1:
            Bundle bundle = message.getData();
            result = bundle.getString("address");
            break;
        default:
            result = null;
        }
        // replace by what you need to do
        myLabel.setText(result);
    }   
}

Don't forget to put the following permission in your Manifest.xml

<uses-permission android:name="android.permission.INTERNET" />
Sortilege answered 12/2, 2011 at 22:35 Comment(4)
the code works flawless, great base to customize furtherPentane
This is correct one else android will through NetworkOnMainThreadException.Alternatively,one can even use a simpler AsyncTask to do thisWeikert
Reverse geocoded address appears multiple times. I dont know why?Exempt
@VineethKuttipurathkottayodan If the same address is appearing multiple times, Its because you have put the function getAddressFromLocation inside onLocationChanged functionCyme
F
37

It looks like there's two things happening here.

1) You've missed the new keyword from before calling the constructor.

2) The parameter you're passing in to the Geocoder constructor is incorrect. You're passing in a Locale where it's expecting a Context.

There are two Geocoder constructors, both of which require a Context, and one also taking a Locale:

Geocoder(Context context, Locale locale)
Geocoder(Context context)

Solution

Modify your code to pass in a valid Context and include new and you should be good to go.

Geocoder myLocation = new Geocoder(getApplicationContext(), Locale.getDefault());   
List<Address> myList = myLocation.getFromLocation(latPoint, lngPoint, 1);

Note

If you're still having problems it may be a permissioning issue. Geocoding implicitly uses the Internet to perform the lookups, so your application will require an INTERNET uses-permission tag in your manifest.

Add the following uses-permission node within the manifest node of your manifest.

<uses-permission android:name="android.permission.INTERNET" />
Fornix answered 23/1, 2009 at 10:25 Comment(2)
Thank you, I think I was working too late last night, not sure what happened to my new. I think I forgot it originally, put it back on when I only had my Locale, and then when I went back, forgot it again.. I appreciate it..Pottery
No worries, I didn't spot it first time either :)Fornix
H
8

The reason for this is the non-existent Backend Service:

The Geocoder class requires a backend service that is not included in the core android framework. The Geocoder query methods will return an empty list if there no backend service in the platform.

Hawsepipe answered 7/10, 2013 at 7:40 Comment(2)
This is the correct answer. The other answers will not work w/o backend.Klagenfurt
This works outside of simulators as far as Google Play Services are runningCultured
D
5

First get Latitude and Longitude using Location and LocationManager class. Now try the code below for Get the city,address info

double latitude = location.getLatitude();
double longitude = location.getLongitude();
Geocoder gc = new Geocoder(this, Locale.getDefault());
try {
    List<Address> addresses = gc.getFromLocation(lat, lng, 1);
    StringBuilder sb = new StringBuilder();
    if (addresses.size() > 0) {
        Address address = addresses.get(0);
        for (int i = 0; i < address.getMaxAddressLineIndex(); i++)
            sb.append(address.getAddressLine(i)).append("\n");
            sb.append(address.getLocality()).append("\n");
            sb.append(address.getPostalCode()).append("\n");
            sb.append(address.getCountryName());
    }

City info is now in sb. Now convert the sb to String (using sb.toString() ).

Deathtrap answered 1/6, 2012 at 12:41 Comment(0)
P
2

Well, I am still stumped. So here is more code.

Before I leave my map, I call SaveLocation(myMapView,myMapController); This is what ends up calling my geocoding information.

But since getFromLocation can throw an IOException, I had to do the following to call SaveLocation

try
{
    SaveLocation(myMapView,myMapController);
}
catch (IOException e) 
{
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Then I have to change SaveLocation by saying it throws IOExceptions :

 public void SaveLocation(MapView mv, MapController mc) throws IOException{
    //I do this : 
    Geocoder myLocation = new Geocoder(getApplicationContext(), Locale.getDefault());   
    List myList = myLocation.getFromLocation(latPoint, lngPoint, 1);
//...
    }

And it crashes every time.

Pottery answered 23/1, 2009 at 23:6 Comment(5)
Could be a permissions problem. The geocoder uses the internet to do the lookups so you need an Internet uses-permission. Updated the answer with details.Fornix
I have the internet permissions on there for the mapping. Very strange why it keeps failing. Let me get a logcat.Pottery
This is the exception I am getting : java.lang.IllegalArgumentException: latitude == 3.2945512E7Pottery
I think I figured it out, it needed the lat/long not E7 (i.e. 32.945512)Pottery
@Pottery what is E7? I am trying to figure out what is wrong with mine?Wasserman
C
0

Use this

Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
Concent answered 7/11, 2016 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.