【问题标题】:Android Geocoder behaves different on some devicesAndroid Geocoder 在某些设备上的行为不同
【发布时间】:2017-11-02 07:58:16
【问题描述】:

我有以下代码,它在某些设备上完美运行,在其他设备上运行良好 getFromLocationName 返回大小为 0 的列表。

例如,在Nexus 6p 它返回正确的结果 在Meizu MX5 中,它返回一个大小为 0 的列表。

我对这两个设备具有相同的权限和 GPS 启用。 Nexus 6p 上的 Android 版本是 7.1.2,Meizu MX5 上的 Android 版本是 5.1

  Geocoder geocoder = new Geocoder(context);
  List<Address> addresses = geocoder.getFromLocationName(place, 3);

注意事项

  1. place 是用户输入的位置(字符串)。
  2. Geocoder 来自 android.location.Geocoder;

那么为什么会有差异呢?是否与设备上的安卓版本有关?

【问题讨论】:

  • 返回值在 javadocs 中描述为:"a list of Address objects. Returns null or empty list if no matches were found or there is no backend service available."
  • 正如 pskink 所说,您没有必要获得所有位置的地址。如果可用,您仍然可以获取国家和州
  • 好的。我忘了提到在两个设备上我使用了相同的位置。那么为什么在 Nexus 6p 上成功而在魅族上却没有呢?正如你所说,如果他们是返回结果的服务,则意味着魅族应该返回与nexus相同的结果,不是吗?
  • 好的,所以Geocoder dosc 说:"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. Use the isPresent() method to determine whether a Geocoder implementation exists." 你检查isPresent() 返回值了吗?
  • 我会检查的。谢谢 :) 所以我想如果我希望它在所有设备上都可用,我应该使用谷歌地图地理编码 api

标签: android location geocoder


【解决方案1】:

Android 中的地理编码器实际上并非在所有设备上都具有相同的行为。我已经使用以下设备测试了地理编码器:

  • 三星(Android 4.4 和 5.1)
  • 联想 (Android 5.0)
  • Vivo (Android 6.0.1)
  • Andromax (Android 5.1.1)
  • 小米(Android 5.1)

返回列表的所有设备,除了小米,它返回零列表。所以,我们不能依赖 Geocoder。解决方案是使用 Google Geocoding API 创建我们自己的 Geocoder 实现,并在列表返回 0 时使用它。

这里是 Geocoder 的实现(我从 SO 中找到,但不记得来源),可以像使用 Geocoder 一样使用:

import android.location.Address;
import android.util.Log;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MyGeocoder {

  public static final String TAG = MyGeocoder.class.getSimpleName();

  static OkHttpClient client = new OkHttpClient();

  public static List<Address> getFromLocation(double lat, double lng, int maxResult) {

    String address = String.format(Locale.US,
        "https://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=false&language="
            + Locale.getDefault().getCountry(), lat, lng);
    Log.d(TAG, "address = " + address);
    Log.d(TAG, "Locale.getDefault().getCountry() = " + Locale.getDefault().getCountry());

    return getAddress(address, maxResult);

  }

  public static List<Address> getFromLocationName(String locationName, int maxResults)  {

    String address = null;
    try {
      address = "https://maps.google.com/maps/api/geocode/json?address=" + URLEncoder.encode(locationName,
          "UTF-8") + "&ka&sensor=false";
      return getAddress(address, maxResults);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static List<Address> getAddress(String url, int maxResult) {
    List<Address> retList = null;

    Request request = new Request.Builder().url(url)
        .header("User-Agent", "OkHttp Headers.java")
        .addHeader("Accept", "application/json; q=0.5")
        .build();
    try {
      Response response = client.newCall(request).execute();
      String responseStr = response.body().string();
      JSONObject jsonObject = new JSONObject(responseStr);

      retList = new ArrayList<Address>();

      if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
        JSONArray results = jsonObject.getJSONArray("results");
        if (results.length() > 0) {
          for (int i = 0; i < results.length() && i < maxResult; i++) {
            JSONObject result = results.getJSONObject(i);
            Address addr = new Address(Locale.getDefault());

            JSONArray components = result.getJSONArray("address_components");
            String streetNumber = "";
            String route = "";
            for (int a = 0; a < components.length(); a++) {
              JSONObject component = components.getJSONObject(a);
              JSONArray types = component.getJSONArray("types");
              for (int j = 0; j < types.length(); j++) {
                String type = types.getString(j);
                if (type.equals("locality")) {
                  addr.setLocality(component.getString("long_name"));
                } else if (type.equals("street_number")) {
                  streetNumber = component.getString("long_name");
                } else if (type.equals("route")) {
                  route = component.getString("long_name");
                }
              }
            }
            addr.setAddressLine(0, route + " " + streetNumber);

            addr.setLatitude(
                result.getJSONObject("geometry").getJSONObject("location").getDouble("lat"));
            addr.setLongitude(
                result.getJSONObject("geometry").getJSONObject("location").getDouble("lng"));
            retList.add(addr);
          }
        }
      }
    } catch (IOException e) {
      Log.e(TAG, "Error calling Google geocode webservice.", e);
    } catch (JSONException e) {
      Log.e(TAG, "Error parsing Google geocode webservice response.", e);
    }

    return retList;
  }
}

注意 Android Geocoder API 中没有发生的每日配额。

【讨论】:

  • 非常感谢,这就是我想要做的:) 所以,你也可以将魅族 MX 5 添加到你的列表中:)
  • 不客气。我很想把魅族 MX 5 作为测试设备!
猜你喜欢
  • 1970-01-01
  • 2021-01-31
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多