为什么Android Geocoder会抛出“Service not Available”异常?

31
该应用程序使用Geocoder对象。在我的Froyo Nexus One上,它运行得很好。但是我在另一台设备上运行完全相同的应用程序(Advent Vega 10英寸平板电脑也运行Froyo),我收到了这个异常:服务不可用。我正在使用的方法是getFromLocationName(),我正在针对Android 1.6 Google API进行构建。
我知道模拟器会抛出此异常,但我认为这是不同的情况。为什么在运行Froyo的一个设备上会抛出它,而在另一个设备上不会呢?
该应用程序是一个位置应用程序,在平板电脑上没有GPS或移动网络,在Wi-Fi连接未提供位置的情况下,用户必须手动指定位置,因此无法使用Geocoder对象是一个坏消息。
我可以添加一种方式让用户在地图上选择位置,但这并不理想。可能我可以直接使用Google Maps API,但我很想先了解问题的本质,因为有一个更简单的解决方案会更好。
希望在将来的版本中,Android将包括一个面向非Geocoder设备的OS级“默认位置”,以便像Google TV这样的设备上的位置感知应用程序可以开箱即用。

我在文档中看到它说:“Geocoder类需要一个不包含在核心Android框架中的后端服务”,但为什么设备供应商不包括它呢?这是一个错误吗? - Ollie C
地理编码器后端是否被认为是经过Google批准的Android分发的一部分?该平板电脑未经Google认证,因此默认情况下不会安装Google Android应用程序(如GMail、Market等)。我怀疑这就是原因。看起来这些类型的设备上的用户可能需要从地图上选择位置,或者我可以直接使用Maps API。排除它似乎很奇怪,我很想知道为什么它不在那里。 - Ollie C
6个回答

28

我向 Google 的 Reto Meier 询问确认我的理论是否正确,他说"正确。地理编码器是 Google API 插件的一部分,它不属于 AOSP。"

因此,任何不带 Play Store、GMail 应用等功能的设备也将缺少地理编码器后端。


1
好的 - 在2.2之前,它在模拟器上运行良好,所以它并不总是这样。 - mxk
1
你对这个有什么看法?它说:“Google APIs add-on还包括一个Geocoder后端服务实现”。这是否意味着构建项目时使用Google API add-on而不是基本的Android SDK将自动将后端包含到.apk中?我注意到你是针对Google API v1.6构建的(而不是基本的Android SDK),所以我猜答案是否定的,因为它对你没有起作用。顺便问一下,你是怎么和Reto Meier交流的? - Tony Chan
1
请注意:如果您正在构建针对API 9或更高版本的应用程序,则有一种方法Geocoder.isPresent()可以告诉您该设备上是否实现了getFromLocation... 方法(我不知道这是否与后端存在相同)。此外,即使没有安装GApps、Market等应用,设备上可能仍然存在后端/实现,如Kindle Fire的情况(在Fire上,Geocoder.isPresent()返回为true),我想亚马逊决定包含一个。 - Tony Chan
5
好的,我之前的评论有误,事实证明即使在Kindle Fire上Geocoder.isPresent()返回true,尝试调用getFromLocationName()仍然会抛出IOException:Service Not Available,我猜这意味着没有后端。因此,isPresent()似乎毫无用处。我还使用了“Google Addon APIs”而不是基本的Android SDK来构建我的项目,但没有任何区别。这让我认真怀疑我在第一个链接中所说的“Google APIs add-on还包括Geocoder后端服务实现”的含义。 - Tony Chan
1
@OllieC 几周前,我成功地实现了 getFromLocationName(),在模拟器和设备上都能正常工作...但是现在 getFromLocation() 抛出了 服务不可用 异常... - Muhammad Babar
显示剩余2条评论

13

似乎有另一个可能的解决方法这个问题的,不幸的是,它被标记为重复问题,因此可能会被忽略。实质上,设备的重新启动可以清除该问题。请注意,我称其为“解决方法”,而不是“解决方案”。 :(


1
我正在寻找一种替代方法来解决这个错误,而不需要重新启动设备。它存在吗? - Umberto
我找到了!为了避免重新启动,你需要将项目构建目标设置为API 16。 在Eclipse中:右键单击项目-> 构建路径-> 配置构建路径-> Android-> 项目构建目标。 - Umberto
将目标API更改为16确实解决了问题吗?有其他人尝试过吗?因为在这个评论中(https://dev59.com/z2Up5IYBdhLWcg3wtZE0#15340668),作者说它最终并不起作用。 - German
这对我有用。我在一个已经安装了Google Play和所有应用的4.1设备上遇到了同样的问题。 - matteo

2

1
一些设备不支持地理编码器,因此您需要创建自己的地理编码器。基本上,您需要创建异步任务请求Google地址并处理JSON响应。使用aquery,我会做这样的事情:
public void asyncJson(String address){
        address = address.replace(" ", "+");

        String url = "http://maps.googleapis.com/maps/api/geocode/json?address="+ address +"&sensor=true";

        aq.ajax(url, JSONObject.class, new AjaxCallback<JSONObject>() {

                @Override
                public void callback(String url, JSONObject json, AjaxStatus status) {                        

                        if(json != null){

                                 //here you work with the response json
                                 JSONArray results = json.getJSONArray("results");                               
                                Toast.makeText(context, results.getJSONObject(1).getString("formatted_address"));

                        }else{                                
                                //ajax error, show error code
                                Toast.makeText(aq.getContext(), "Error:" + status.getCode(), Toast.LENGTH_LONG).show();
                        }
                }
        });        
}

1
在浪费了数个小时之后,我找到了最简单的解决方案。
我只是重启了我的设备,然后它开始工作了。
看起来,问题是由于某些操作系统级别的缓存问题引起的。希望这对你也有用。

0

我曾经遇到过同样的问题。我使用了以下函数。

注意:

请使用您的Activity的上下文(context),不要使用getApplicationContext()来调用以下函数。

public static Address getLocalityFrmGeoCoder(Context context, Location mLocation) {
        try {
            if(mLocation!=null){
            Geocoder gCoder = new Geocoder(context, Locale.getDefault());
            List<Address> address = gCoder.getFromLocation(mLocation.getLatitude(), mLocation.getLongitude(), 1);
            if (address.size() > 0) {
                return address.get(0);
            }
            }

        } catch (Exception e) {
            Log.d("GEOCODER", "GEOCODER EXCEPTION");
            e.printStackTrace();

        }
    return null;
}

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