从Google Place API在Android上获取城市名称和邮政编码

25

我正在使用具有自动完成功能的Google Place API for Android

一切正常,但是当像这里所示获取结果时,我无法得到城市和邮政编码信息。

    private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback
        = new ResultCallback<PlaceBuffer>() {
    @Override
    public void onResult(PlaceBuffer places) {
        if (!places.getStatus().isSuccess()) {
            // Request did not complete successfully
            Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());

            return;
        }
        // Get the Place object from the buffer.
        final Place place = places.get(0);

        // Format details of the place for display and show it in a TextView.
        mPlaceDetailsText.setText(formatPlaceDetails(getResources(), place.getName(),
                place.getId(), place.getAddress(), place.getPhoneNumber(),
                place.getWebsiteUri()));

        Log.i(TAG, "Place details received: " + place.getName());
    }
};

这个Place类并不包含这些信息。我可以获得完整的人类可读地址、纬度和经度等。

我怎样才能从自动完成结果中获取城市和邮政编码呢?

6个回答

29

通常情况下,无法从地点中直接获取城市名称,但你可以通过以下方式轻松获得:
1)获取地点的坐标(或以其他方式获取它们);
2)使用地理编码器根据坐标检索城市。
操作步骤如下:

private Geocoder mGeocoder = new Geocoder(getActivity(), Locale.getDefault());

// ... 

 private String getCityNameByCoordinates(double lat, double lon) throws IOException {

     List<Address> addresses = mGeocoder.getFromLocation(lat, lon, 1);
     if (addresses != null && addresses.size() > 0) {
         return addresses.get(0).getLocality();
     }
     return null;
 }

必须添加try和catch块来处理IOException,否则它将无法编译。 - S bruce
它将会编译通过。仔细检查方法声明。 - Leo DroidCoder

21

可以通过两个步骤获取城市名称和邮政编码

1)调用Web服务到https://maps.googleapis.com/maps/api/place/autocomplete/json?key=API_KEY&input=your_inpur_char,JSON中包含place_id字段,可在第2步中使用。

2)再次调用Web服务到https://maps.googleapis.com/maps/api/place/details/json?key=API_KEY&placeid=place_id_retrieved_in_step_1。这将返回一个JSON,其中包含address_components。遍历types以查找localitypostal_code 可以获得城市名称和邮政编码。

实现代码:

JSONArray addressComponents = jsonObj.getJSONObject("result").getJSONArray("address_components");
        for(int i = 0; i < addressComponents.length(); i++) {
            JSONArray typesArray = addressComponents.getJSONObject(i).getJSONArray("types");
            for (int j = 0; j < typesArray.length(); j++) {
                if (typesArray.get(j).toString().equalsIgnoreCase("postal_code")) {
                    postalCode = addressComponents.getJSONObject(i).getString("long_name");
                }
                if (typesArray.get(j).toString().equalsIgnoreCase("locality")) {
                    city = addressComponents.getJSONObject(i).getString("long_name")
                }
            }
        }

请注意 - 这种技术可能会在某些地方引起问题 - 我特别在一些纽约地址 - Staten Island,Brooklyn和Bronx以及Clifton Park地址中遇到了这个问题,使用“sublocality”,“administrative_area_level_3”或其他类型而不是“locality”作为地址中使用的正确“城市”名称 - Kevin Foster

10

很遗憾,目前Android API无法提供此信息。


5
private Geocoder geocoder;
private final int REQUEST_PLACE_ADDRESS = 40;

onCreate

Places.initialize(context, getString(R.string.google_api_key));

Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.FULLSCREEN, Arrays.asList(Place.Field.ADDRESS_COMPONENTS, Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG)).build(context);
startActivityForResult(intent, REQUEST_PLACE_ADDRESS);

onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_PLACE_ADDRESS && resultCode == Activity.RESULT_OK) {
        Place place = Autocomplete.getPlaceFromIntent(data);
        Log.e("Data",Place_Data: Name: " + place.getName() + "\tLatLng: " + place.getLatLng() + "\tAddress: " + place.getAddress() + "\tAddress Component: " + place.getAddressComponents());

        try {
            List<Address> addresses;
            geocoder = new Geocoder(context, Locale.getDefault());

            try {
                addresses = geocoder.getFromLocation(place.getLatLng().latitude, place.getLatLng().longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
                String address1 = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
                String address2 = addresses.get(0).getAddressLine(1); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
                String city = addresses.get(0).getLocality();
                String state = addresses.get(0).getAdminArea();
                String country = addresses.get(0).getCountryName();
                String postalCode = addresses.get(0).getPostalCode();

                Log.e("Address1: ", "" + address1);
                Log.e("Address2: ", "" + address2);
                Log.e("AddressCity: ", "" + city);
                Log.e("AddressState: ", "" + state);
                Log.e("AddressCountry: ", "" + country);
                Log.e("AddressPostal: ", "" + postalCode);
                Log.e("AddressLatitude: ", "" + place.getLatLng().latitude);
                Log.e("AddressLongitude: ", "" + place.getLatLng().longitude);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
            //setMarker(latLng);
        }
    }
}

0

您可以通过 Geoencoder.getFromLocation(lat, long, maxResults) 提供的地址数组获取地址详细信息。

这里是 Kotlin 的示例代码:

private fun getPincode(latitude: Double, longitude: Double): String
 {
                var addresses: List<Address>? = null
                var city: String? = ""
                val geoCoder = Geocoder(this, Locale.getDefault())
              
        
                try {
                    addresses = geoCoder.getFromLocation(latitude, longitude, 1)
                    if (addresses != null && addresses.isNotEmpty()) {
    
                        val countryName = addresses[0].countryName
                        val state = addresses[0].subAdminArea
                        val address = addresses[0].featureName
                        val island = addresses[0].adminArea
        
                        try {
                            city = addresses[0].locality
                            if (city == null) city = addresses[0].subLocality
                            if (city == null) city = addresses[0].subAdminArea
                            if (city == null) city = addresses[0].adminArea
                            //  addressCity = city
                        } catch (e: Exception) {
                            //  addressCity = ""
                        }
        
                        val pinCode = addresses[0].postalCode
                        val latitudeAddress = addresses[0].latitude
                        val longitudeAddress = addresses[0].longitude
                       
                        return pinCode
                      }
                } catch (e: IOException) {
                    e.printStackTrace()
                    
                }
        
                return ""
}

-2

不是最好的方法,但以下内容可能会有用:

 Log.i(TAG, "Place city and postal code: " + place.getAddress().subSequence(place.getName().length(),place.getAddress().length()));

使用地理编码器绝对是解决此问题的更好方法,参考 https://dev59.com/W5Hea4cB1Zd3GeqPmDbS#35992244。 - RayChongJH

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