Geocoder.getFromLocation在Android模拟器上抛出IOException异常

15

我使用Android模拟器2.2 API 8,但不断收到IOException错误。

03-05 19:42:11.073: DEBUG/SntpClient(58): request time failed: java.net.SocketException: Address family not supported by protocol
03-05 19:42:15.505: WARN/System.err(1823): java.io.IOException: Service not Available

这是我的代码:

private LocationManager manager = null;
LocationListener locationListener = null;
double latitude = 0;
double longtitude = 0;
List<Address> myList = null;

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    // httpTranslateGet();
    try
    {


        manager = (LocationManager) this
                .getSystemService(Context.LOCATION_SERVICE);


        initLocationListener();

        manager.requestLocationUpdates(manager.GPS_PROVIDER, 0, 0,
                locationListener);

    }
    catch (Exception e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

private void initLocationListener()
{
    locationListener = new LocationListener()
    {

        @Override
        public void onLocationChanged(android.location.Location location)
        {
            if (location != null)
            {

                latitude = location.getLatitude();
                longtitude = location.getLongitude();


                try
                {
                    Geocoder geocoder = new Geocoder(WeatherCastDemo.this, Locale.getDefault());
                    List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
                    myList = geocoder.getFromLocation(
                            location.getLatitude(),
                            location.getLongitude(), 10);

                    StringBuilder sb = new StringBuilder();
                    if (myList.size() > 0)
                    {
                        Address address = myList.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());

                    }
                }

                catch (IOException e)
                {
                    e.printStackTrace();
                }

            }

        }

        @Override
        public void onProviderDisabled(String arg0)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onProviderEnabled(String provider)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onStatusChanged(String provider, int status,
                Bundle extras)
        {

        }
    };
}

有人有任何想法吗?

我已经成功地使用模拟器2.1 API 7完成了它,但反向地理编码总是返回一个空结果。有人能确认我的代码吗?

谢谢。

谢谢,
Ray。


你是否在防火墙或代理下? - Tanmay Mandal
你的模拟器是否已连接到互联网?请通过浏览器进行检查。 - Jonathan Roth
我没有被防火墙/代理所限制,是的,我可以连接到互联网。 - rayman
哪一行抛出了异常? - Thomas
7个回答

21

这是模拟器的已知问题,但实际设备上可以正常工作。

在2.2 API 8上,您将收到以下堆栈跟踪信息

java.io.IOException: Service not Available
 at android.location.Geocoder.getFromLocation(Geocoder.java:117)

查看此处以获取更多信息(和可能的解决方法),请参阅以下网址:

http://code.google.com/p/android/issues/detail?id=8816

如果在较低版本的API中使用GeoCoder遇到问题,您应该检查堆栈跟踪。 有时我会遇到以下问题:

java.io.IOException: Unable to parse response from server
 at android.location.Geocoder.getFromLocation(Geocoder.java:124) 

这可能是来自Google的服务器端问题或客户端问题(如网络连接)。

如果Geocoder返回了一个空列表,则需要检查设备(模拟器或实际手机)上是否有适当的Geocoder实现,可以使用Geocoder对象上的isPresent()方法进行检查。

http://developer.android.com/reference/android/location/Geocoder.html

此外,在模拟器上运行时,请确保您的AVD映像已设置为使用Google API。


我已经使用模拟器2.1和API7成功完成了它,但是反向编码代码总是返回空结果,你有什么想法为什么会这样? - rayman
Rayman:我已更新答案……当执行Geocoder查找时,你是否会收到异常? - ddewaele
在列表地址(List<Address> addresses)中,只是返回一个空结果。 - rayman
啊,好的...请检查更新后的答案...检查一下是否已经有实现,并且您的AVD是否已经设置了Google APIs。 - ddewaele
是的,它已经设置了Google API,但我收到了“无法解析服务器响应”的错误。 - rayman
Geocoder 文档所述,Geocoder.isPresent() "如果实现了 Geocoder 方法 getFromLocation 和 getFromLocationName,则返回 true。" 这并不意味着您可以成功使用它们。 当我在 AVD 2.3.3 上测试我的应用程序时,我会得到 java.io.IOException: Service not Available 错误,而 Geocoder.isPresent() 返回 true。 - a.b.d

10
您可以按照以下方式使用 Google Place API:
创建一个方法,返回类似以下 HTTP 请求的响应JSONObject
public static JSONObject getLocationInfo(String address) {
    StringBuilder stringBuilder = new StringBuilder();
    try {

    address = address.replaceAll(" ","%20");    

    HttpPost httppost = new HttpPost("http://maps.google.com/maps/api/geocode/json?address=" + address + "&sensor=false");
    HttpClient client = new DefaultHttpClient();
    HttpResponse response;
    stringBuilder = new StringBuilder();


        response = client.execute(httppost);
        HttpEntity entity = response.getEntity();
        InputStream stream = entity.getContent();
        int b;
        while ((b = stream.read()) != -1) {
            stringBuilder.append((char) b);
        }
    } catch (ClientProtocolException e) {
    } catch (IOException e) {
    }

    JSONObject jsonObject = new JSONObject();
    try {
        jsonObject = new JSONObject(stringBuilder.toString());
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return jsonObject;
}

现在像下面这样将JSONObject传递给getLatLong()方法

public static GeoPoint  getLatLong(JSONObject jsonObject) {

        Double lon = new Double(0);
        Double lat = new Double(0);

        try {

            lon = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
                .getJSONObject("geometry").getJSONObject("location")
                .getDouble("lng");

            lat = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
                .getJSONObject("geometry").getJSONObject("location")
                .getDouble("lat");

        } catch (Exception e) {
            e.printStackTrace();

        }

        return new GeoPoint((int) (lat * 1E6), (int) (lon * 1E6));
    }

已经测试通过,可在API level 8上运行,希望能帮到您。


在我的Android 2.3.3中无法工作,它只显示相同的错误,即无法获取连接工厂客户端。 - Harpreet
这对于所有的Google API 7、8、10都可以正常工作,我会在所有上进行测试...也许你在某些方面是错误的...只需发布你的代码... - a4ankur
它对我也起作用了。之前我在搞KML解析,头痛得很。但这个确实是一个非常好的简单解决方案。为GMaps喝彩! - YuDroid
我一直收到一个UnknownHostException错误。 我已经完成了以下操作:1> 在正确的位置添加了INTERNET权限2> 通过使用模拟器浏览器检查了互联网连接3> 我重新检查了代码!它在“response = client.execute(httppost);”处抛出异常。 - Axe
1
谢谢提供代码。但是有一个问题:为什么使用HTTP POST请求,明显这是带有一些查询参数的HTTP GET请求。 - AndyB

4

我读了@ddewaele提到的讨论帖,有人说重新启动可以解决问题。确实如此。顺便提一下,我的设备使用的是Android 4.1版本。


非常感谢,是的它奏效了...真的是重新启动解决了!!!我花费了一整天的时间在检查我的代码、网络权限等方面...最终这个方法让我愉快了,但我仍然不知道原因。为什么呢? - Asif Sb

2

纬度和经度分别是您的值

Geocoder geocoder = new Geocoder(getBaseContext(), Locale.ENGLISH);
        try {
            List<Address> addresses = geocoder.getFromLocation(latitude,
                    longitude, 1);

            if (addresses.size() > 0) {
                Address returnedAddress = addresses.get(0);
                StringBuilder strReturnedAddress = new StringBuilder(
                        "Address:\n");
                for (int i = 0; i < returnedAddress
                        .getMaxAddressLineIndex(); i++) {
                    strReturnedAddress.append(
                            returnedAddress.getAddressLine(i)).append("\n");
                }
                adrs.setText(strReturnedAddress.toString());
            } else {
                adrs.setText("No Address returned!");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }

1
以上代码稍作修改,即可替换getFromLocationName调用,因为在某些终端上似乎不受支持。
private static List<Address> getAddrByWeb(JSONObject jsonObject){
    List<Address> res = new ArrayList<Address>();
    try
    {
        JSONArray array = (JSONArray) jsonObject.get("results");
        for (int i = 0; i < array.length(); i++)
        {
            Double lon = new Double(0);
            Double lat = new Double(0);
            String name = "";
            try
            {
                lon = array.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getDouble("lng");

                lat = array.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getDouble("lat");
                name = array.getJSONObject(i).getString("formatted_address");
                Address addr = new Address(Locale.getDefault());
                addr.setLatitude(lat);
                addr.setLongitude(lon);
                addr.setAddressLine(0, name != null ? name : "");
                res.add(addr);
            }
            catch (JSONException e)
            {
                e.printStackTrace();

            }
        }
    }
    catch (JSONException e)
    {
        e.printStackTrace();

    }

    return res;
}

}


0

您可以将Mr.cyclopes49提供的代码作为两个函数使用,并在onCreate()方法中添加对getLatLong()getLocationInfo()函数的调用,它可以正常工作。示例语句如下:

JSONObject jo = this.getLocationInfo("vizianagaram");
GeoPoint p=this.getLatLong(jo);
Toast.makeText(getBaseContext(), 
                        p.getLatitudeE6() / 1E6 + "," + 
                        p.getLongitudeE6() /1E6 , 
                        Toast.LENGTH_SHORT).show();

这个很好用!


0
fun getPostalCode(context: Context, latitude: Double, longitude: Double) : String 
{
    val geocoder = Geocoder(context, Locale.getDefault())
    var postalCode = ""
    try {
        val address = geocoder.getFromLocation(latitude, longitude, 1)

        if (address != null && address[0] != null && address[0].postalCode != null)
            postalCode = address.get(0).postalCode

    }
    catch (e: IOException) {
        Log.e(TAG, e.toString())
    }
    return postalCode
}

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