Android Geocoder behaves different on some devices

て烟熏妆下的殇ゞ 提交于 2019-11-28 06:24:24

问题


I have the below code, it works perfectly on some devices and in others the function getFromLocationName return a list with size 0.

For example, in Nexus 6p it returns the correct result and in Meizu MX5 it returns a list with size 0.

I have the same permissions and GPS enable for both devices. Android version on the Nexus 6p is 7.1.2 and on Meizu MX5 is 5.1

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

Notes:

  1. place is the location the user entered (String).
  2. Geocoder is from android.location.Geocoder;

So why the difference? Is it related to the Android version on the devices?


回答1:


Geocoder in Android is really don't have the same behaviour on all devices. I have tested the Geocoder with the following devices:

  • Samsung (Android 4.4 and 5.1)
  • Lenovo (Android 5.0)
  • Vivo (Android 6.0.1)
  • Andromax (Android 5.1.1)
  • Xiaomi (Android 5.1)

All the devices returning the list but Xiaomi, it returns zero lists. So, we can't depend on Geocoder. The solution is to create our own Geocoder implementation using Google Geocoding API and use it whenever the list returns 0.

Here the implementation of Geocoder (I found it from SO, but can't remember the source) which can be used exatly like using the 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;
  }
}

Be aware of the daily quota which didn't happen in Android Geocoder API.



来源:https://stackoverflow.com/questions/47070264/android-geocoder-behaves-different-on-some-devices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!