安卓:反向地理编码 - getFromLocation

55

我正在尝试基于经纬度获取地址。看起来这样做应该可以吗?

Geocoder myLocation = Geocoder(Locale.getDefault());
    List myList = myLocation.getFromLocation(latPoint,lngPoint,1);
问题在于我一直收到:The method Geocoder(Locale) is undefined for the type savemaplocation。
任何帮助都将是有益的。谢谢。
感谢,我首先尝试了context、locale那个构造函数,但失败了,并查看了一些其他的构造函数(我曾看到一个只提到了locale的构造函数)。不管怎样,
它没有起作用,因为我仍然得到:The method Geocoder(Context, Locale) is undefined for the type savemaplocation。
我已经包含了:import android.location.Geocoder;
7个回答

70
下面的代码片段对我很有用(lat和lng是在此之前声明的双精度变量):
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);

1
我也尝试了这个,每次我尝试查看地址列表时,它都崩溃了。不确定发生了什么。我将在一两天内尝试使用新应用程序来查看我能找到什么。 - Chrispix
4
我觉得这篇文章对于定位东西非常有帮助: http://blogoscoped.com/archive/2008-12-15-n14.html - Wilfred Knievel
1
同时,我在清单文件中添加了以下两个权限: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />当我漏掉其中一个(不记得是哪一个)时,应用程序会抛出一个非常没有帮助性的错误。 - Wilfred Knievel
我该如何向这个类添加API密钥,以便可以获得更多的请求? - Olsi Saqe
使用Locale.US更好吗?因为有时getDefault()会返回一些问题,比如随机语言的地址,不是吗? - portfoliobuilder
1
在2019年(api>= 26 SDK)中,我们是否有一种不需要传递上下文即可获取地址的方法? - Ponomarenko Oleh

51

以下是使用线程和处理程序的完整示例代码,以在不阻塞用户界面的情况下获取地理编码器答案。

地理编码器调用过程可以位于 Helper 类中。

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();
}

以下是在您的 UI Activity 中调用此 Geocoder 程序的方法:

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

并且在你的用户界面中显示结果的处理程序:

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);
    }   
}

别忘了在你的Manifest.xml中加入以下权限。

<uses-permission android:name="android.permission.INTERNET" />

代码运行完美,是进一步定制的绝佳基础。 - John
这是正确的方法,否则Android会抛出“NetworkOnMainThreadException”。另外,也可以使用更简单的“AsyncTask”来完成此操作。 - Nezam
1
反向地理编码的地址出现了多次。我不知道为什么? - Vineeth Kuttipurath kottayodan
@VineethKuttipurathkottayodan 如果同一地址出现多次,那是因为您将函数getAddressFromLocation放在了onLocationChanged函数内部。 - coder

37

看起来这里发生了两件事情。

1) 你在调用构造函数之前漏掉了new关键字。

2) 你传递给Geocoder构造函数的参数不正确。它期望传入一个Context,而你传递了Locale

Geocoder有两个构造函数,都需要一个Context参数,其中一个还需要一个Locale参数:

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

解决方案

修改您的代码,传递有效的上下文(Context),包括new关键字,这样您就可以顺利运行了。

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

注意

如果您仍然遇到问题,可能是权限问题。地理编码隐式使用互联网执行查找,因此您的应用程序需要在清单文件中添加一个INTERNET uses-permission标签。

请在清单文件的manifest节点内添加以下uses-permission节点。

<uses-permission android:name="android.permission.INTERNET" />

谢谢,我想昨晚工作太晚了,不确定我的新东西发生了什么。我想我最初忘记了它,在只有我的Locale时把它放回去,然后当我回来时,又忘记了它...我很感激。 - Chrispix
没关系,我第一次也没有注意到 :) - Reto Meier

8
这是因为缺乏后端服务:

Geocoder类需要一个后端服务,这个服务不包含在核心Android框架中。如果平台上没有后端服务,Geocoder查询方法将返回一个空列表。


这是正确的答案。其他答案没有后端将无法工作。 - ajeh
1
只要 Google Play 服务正在运行,这个程序在模拟器之外也能正常工作。 - Gabe

5
首先使用Location和LocationManager类获取纬度和经度。现在尝试以下代码以获取城市和地址信息。
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());
    }

现在,城市信息已经存储在sb中。现在使用sb.toString()将sb转换为字符串。


2

我还是有些困惑。这里提供更多的代码。

在离开我的地图之前,我会调用SaveLocation(myMapView,myMapController); 这将调用我的地理编码信息。

但是因为getFromLocation可能会抛出IOException异常,所以我必须采取以下措施来调用SaveLocation。

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

然后我必须通过说它会抛出IOExceptions来更改SaveLocation:

 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);
//...
    }

每次都会崩溃。

可能是权限问题。地理编码器使用互联网进行查找,因此需要一个Internet使用权限。已更新答案并详细说明。 - Reto Meier
我在那里有互联网权限用于映射。非常奇怪为什么它一直失败。让我获取一个logcat。 - Chrispix
这是我得到的异常:java.lang.IllegalArgumentException: latitude == 3.2945512E7 - Chrispix
1
我想我弄清楚了,它需要的是纬度/经度而不是E7(即32.945512)。 - Chrispix
@Chrispix,E7是什么?我正在尝试弄清楚我的问题出在哪里? - Gabriel Fair

0

使用它

Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接