通过自动完成地点API返回的place_id获取纬度和经度

56

我正在使用Google自动完成地点API在我的应用程序中搜索地点,现在我想获取我搜索的位置的纬度和经度。如何从Google在Android中返回的自动完成地点API结果中获取纬度和经度?


使用Geocoder。请参考:http://developer.android.com/reference/android/location/Geocoder.html - shyam
当前API不允许像Web API那样使用一个请求完成此操作。请点赞 https://issuetracker.google.com/issues/35828699,以请求在预测响应中公开坐标。 - AlexKorovyansky
这是正确的解决方案 https://stackoverflow.com/a/70751725/6236752 - Nouman Ch
13个回答

50
以下代码片段使用Google Places API for android 对我很有用。

以下代码片段使用Google Places API for android 对我很有用

Places.GeoDataApi.getPlaceById(mGoogleApiClient, placeId)
    .setResultCallback(new ResultCallback<PlaceBuffer>() {
  @Override
  public void onResult(PlaceBuffer places) {
    if (places.getStatus().isSuccess()) {
      final Place myPlace = places.get(0);
      LatLng queriedLocation = myPlace.getLatLng();
      Log.v("Latitude is", "" + queriedLocation.latitude);
      Log.v("Longitude is", "" + queriedLocation.longitude);
    }
    places.release();
  }
});

访问Google Places API for Android以获得从地点检索数据的完整方法列表。


placeId究竟是什么?是用户在自动完成文本视图中输入的地址吗? - Choy
1
@Choy 地点ID,一个哈希字符串。 - lasec0203

44

Google Place Details是答案。

从您获取的place_id,查询类似这样的Place Details https://maps.googleapis.com/maps/api/place/details/json?placeid={placeid}&key={key},并且您可以从result.geometry.location JSON 中获取latlng


1
它对我没用。它的响应是无效请求。 - user11029823

12

使用Place.Field.LAT_LNG可以获取地点的纬度和经度。

 autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, 
 Place.Field.NAME,Place.Field.LAT_LNG));

然后获取经纬度

LatLng destinationLatLng = place.getLatLng();

并且可以透过吐司看到

 destlat = destinationLatLng.latitude;
 destLon = destinationLatLng.longitude;
 Toast.makeText(getApplicationContext(), "" + destlat + ',' + destLon, Toast.LENGTH_LONG).show();

在 Kotlin 中是否有这个可能? - MilkBottle
1
这是如何在 Kotlin 中实现的。val fields = ArrayList<Place.Field>() fields.add(Place.Field.NAME) fields.add(Place.Field.ADDRESS) fields.add(Place.Field.LAT_LNG) startActivityForResult(Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields).build(mContext), AUTOCOMPLETE_REQUEST_CODE); - Sadda Hussain

7
每个在place-autocomplete响应中返回的地点都有一个Id和一个reference字符串,如此处所述。
请使用其中一个(首选Id,因为引用已弃用)查询Places API以获取有关该地点的完整信息(包括纬度/经度):https://developers.google.com/places/documentation/details#PlaceDetailsRequests 关于shyam的评论-只有在自动完成响应中获得完整地址时,地理编码才起作用,这并不总是成立。另外,地理编码会给出可能的结果列表,因为您在自动完成响应中获得的位置描述不是唯一的。根据您的需要,地理编码可能就足够了。

6

根据最新版本的AutoComplete文档

选项1:嵌入一个AutocompleteSupportFragment

AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
            getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);

 autocompleteFragment
    .setPlaceFields(Arrays.asList(Place.Field.ID, 
    Place.Field.NAME,Place.Field.LAT_LNG,Place.Field.ADDRESS));

选项2:使用意图启动自动完成活动。
List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME,Place.Field.LAT_LNG,Place.Field.ADDRESS);

// Start the autocomplete intent.
Intent intent = new Autocomplete.IntentBuilder(
        AutocompleteActivityMode.FULLSCREEN, fields)
        .build(this);
startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);

无论您对哪个领域感兴趣,都需要按照上述所述进行提及。

您将获得以下结果:

 onPlaceSelected: 

{

"a":"#90, 1st Floor, Balaji Complex, Kuvempu Main Road, Kempapura, Hebbal 
    Kempapura, Bengaluru, Karnataka 560024, India",
"b":[],
"c":"ChIJzxEsY4QXrjsRQiF5LWRnVoc",
"d":{"latitude":13.0498176,"longitude":77.600347},
    "e":"CRAWLINK Networks Pvt. Ltd."
}

注意:显示的结果是通过将Place对象解析为json格式得到的。

1
这就是确切的答案。谢谢。 - Naveed Ahmad

5
在函数下面添加这些代码行。
 autocomplete.addListener('place_changed', function() {});
 var place = autocomplete.getPlace();
 autocomplete.setFields(['place_id', 'geometry', 'name', 'formatted_address']);
 var lng = place.geometry.location.lng();
 var lat = place.geometry.location.lat();
 var latlng = {lat , lng};
 console.log(latlng);

3
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

   if (requestCode == Constant.REQUEST_LOCATION_CODE) {

        Place place = PlaceAutocomplete.getPlace(this, data);

        if (place != null) {
            LatLng latLng = place.getLatLng();
            mStringLatitude = String.valueOf(latLng.latitude);
            mStringLongitude = String.valueOf(latLng.longitude);
            EditTextAddress.setText(place.getAddress());
        }
    }
}

使用上述代码,您可以获取LatLng以及字符串地址。随时在需要的地方使用LatLng。


数据应该是什么?意图不明确。 - mitsest
place.getLatLng() 大部分时间返回 null。 - Sadda Hussain

2
地理编码是一种非常间接的解决方案,正如第二个回答者所说,如果您输入“苹果店”,它可能不会返回完整地址。相反:
Place_ID 包含您需要的所有信息。我假设您知道如何从 Places API 获取 place_id(如果不知道,他们有一个完整的示例)。
然后使用 place_id 按照此文档中的说明发出第二个请求以获取地点详细信息(包括几何部分下的纬度和经度): https://developers.google.com/places/documentation/details?utm_source=welovemapsdevelopers&utm_campaign=mdr-devdocs

这非常有用,可以获取某个地方的完整数据。 - dianakarenms

2

1
这段代码允许根据自动完成返回的标识符获取地点的纬度和经度。
public class PlacesDetails {
  private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
  private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
  private static final String TYPE_DETAIL = "/details";
  private static final String OUT_JSON = "/json";

  //private static final String API_KEY = "------------ make your specific key ------------; // cle pour le serveur         
  public PlacesDetails() {
    // TODO Auto-generated constructor stub
  }
  public ArrayList < Double > placeDetail(String input) {
    ArrayList < Double > resultList = null;

    HttpURLConnection conn = null;
    StringBuilder jsonResults = new StringBuilder();
    try {
      StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_DETAIL + OUT_JSON);
      sb.append("?placeid=" + URLEncoder.encode(input, "utf8"));
      sb.append("&key=" + API_KEY);
      URL url = new URL(sb.toString());
      //Log.e("url", url.toString());
      System.out.println("URL: " + url);
      System.out.println("******************************* connexion au serveur *****************************************");
      //Log.e("nous sommes entrai de test la connexion au serveur", "test to connect to the api");
      conn = (HttpURLConnection) url.openConnection();
      InputStreamReader in = new InputStreamReader(conn.getInputStream());

      // Load the results into a StringBuilder
      int read;
      char[] buff = new char[1024];
      while ((read = in .read(buff)) != -1) {
        jsonResults.append(buff, 0, read);
      }
      System.out.println("le json result" + jsonResults.toString());
    } catch (MalformedURLException e) {
      //Log.e(LOG_TAG, "Error processing Places API URL", e);
      return resultList;
    } catch (IOException e) {
      //Log.e(LOG_TAG, "Error connecting to Places API", e);
      return resultList;
    } finally {
      if (conn != null) {
        conn.disconnect();
      }
      System.out.println("******************************* fin de la connexion*************************************************");
    }

    try {
      // Create a JSON object hierarchy from the results
      //Log.e("creation du fichier Json", "creation du fichier Json");
      System.out.println("fabrication du Json Objet");
      JSONObject jsonObj = new JSONObject(jsonResults.toString());
      //JSONArray predsJsonArray = jsonObj.getJSONArray("html_attributions");
      JSONObject result = jsonObj.getJSONObject("result").getJSONObject("geometry").getJSONObject("location");
      System.out.println("la chaine Json " + result);
      Double longitude = result.getDouble("lng");
      Double latitude = result.getDouble("lat");
      System.out.println("longitude et latitude " + longitude + latitude);
      resultList = new ArrayList < Double > (result.length());
      resultList.add(result.getDouble("lng"));
      resultList.add(result.getDouble("lat"));
      System.out.println("les latitude dans le table" + resultList);

    } catch (JSONException e) {
      ///Log.e(LOG_TAG, "Cannot process JSON results", e);
    }

    return resultList;
  }
  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    PlacesDetails pl = new PlacesDetails();
    ArrayList < Double > list = new ArrayList < Double > ();
    list = pl.placeDetail("ChIJbf7h4osSYRARi8SBR0Sh2pI");
    System.out.println("resultat de la requette" + list.toString());
  }
}

我认为你应该添加这应该在异步线程中运行的说明。 - Taslim Oseni

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