Search code examples
c#iosgoogle-mapsxamarin

Xamarin Google Maps API


I'm using the code below to get the city name of a given Latitude and Longitude.

But the code stops when this line is running:

var responseElement = XElement.Parse(response);

It stops responding and doesn't throw any exception.

I'm guessing it may be a problem with the asynchronous call.

Can anyone help me with this, or suggest a similar code that use the iOS SDK?

private async Task<string> ReturnCity(string lat, string lon)
{
    string city = "None";
    string baseUri = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false", lat, lon);
    HttpClient client = new HttpClient();
    var response = await client.GetStringAsync(baseUri);
    var responseElement = XElement.Parse(response);
    IEnumerable<XElement>statusElement = from st in responseElement.Elements("status") select st;
    if (statusElement.FirstOrDefault() != null)
    {
        string status = statusElement.FirstOrDefault().Value;
        if (status.ToLower() == "ok")
        {
            IEnumerable<XElement> resultElement = from rs in responseElement.Elements("result") select rs;
            if (resultElement.FirstOrDefault() != null)
            {
                IEnumerable<XElement> addressElement = from ad in resultElement.FirstOrDefault().Elements("address_component") select ad;
                foreach (XElement element in addressElement)
                {
                    IEnumerable<XElement> typeElement = from te in element.Elements("type") select te;
                    string type = typeElement.FirstOrDefault().Value;
                    if(type=="locality")
                    {
                        IEnumerable<XElement> cityElement = from ln in element.Elements("long_name") select ln;
                        city = cityElement.FirstOrDefault().Value;
                        return city;
                        break;
                    }
                }
            }
        }
    }
    return city;
}

I went through the debugger and found the value of response. It looks like a valid XML. Any thoughts?

<?xml version="1.0" encoding="UTF-8"?>
<GeocodeResponse>
 <status>OK</status>
 <result>
  <type>airport</type>
  <type>transit_station</type>
  <type>establishment</type>
  <formatted_address>Lisbon Portela Airport (LIS), Alameda das Comunidades Portuguesas, 1700-111 Lisboa, Portugal</formatted_address>
  <address_component>
   <long_name>Lisbon Portela Airport</long_name>
   <short_name>Lisbon Portela Airport</short_name>
  </address_component>
  <address_component>
   <long_name>Alameda das Comunidades Portuguesas</long_name>
   <short_name>Alameda das Comunidades Portuguesas</short_name>
   <type>route</type>
  </address_component>
  <address_component>
   <long_name>Lisboa</long_name>
   <short_name>Lisboa</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisboa</long_name>
   <short_name>Lisboa</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>1700-111</long_name>
   <short_name>1700-111</short_name>
   <type>postal_code</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7755936</lat>
    <lng>-9.1353667</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.7623900</lat>
     <lng>-9.1475505</lng>
    </southwest>
    <northeast>
     <lat>38.7994779</lat>
     <lng>-9.1236185</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.7623900</lat>
     <lng>-9.1475505</lng>
    </southwest>
    <northeast>
     <lat>38.7994779</lat>
     <lng>-9.1236185</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJgwHZFkYyGQ0RRm0DWD6lZgo</place_id>
 </result>
 <result>
  <type>route</type>
  <formatted_address>Lisbon Portela Airport (LIS), Rua E, 1700-111 Lisboa, Portugal</formatted_address>
  <address_component>
   <long_name>Rua E</long_name>
   <short_name>R. E</short_name>
   <type>route</type>
  </address_component>
  <address_component>
   <long_name>Lisbon Portela Airport</long_name>
   <short_name>Lisbon Portela Airport</short_name>
  </address_component>
  <address_component>
   <long_name>Lisboa</long_name>
   <short_name>Lisboa</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisboa</long_name>
   <short_name>Lisboa</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>1700-111</long_name>
   <short_name>1700-111</short_name>
   <type>postal_code</type>
  </address_component>
  <address_component>
   <long_name>1700</long_name>
   <short_name>1700</short_name>
   <type>postal_code_prefix</type>
   <type>postal_code</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7757984</lat>
    <lng>-9.1304833</lng>
   </location>
   <location_type>GEOMETRIC_CENTER</location_type>
   <viewport>
    <southwest>
     <lat>38.7744765</lat>
     <lng>-9.1317496</lng>
    </southwest>
    <northeast>
     <lat>38.7771745</lat>
     <lng>-9.1290516</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.7748799</lat>
     <lng>-9.1307609</lng>
    </southwest>
    <northeast>
     <lat>38.7767711</lat>
     <lng>-9.1300403</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJjdzMckIyGQ0RvIXYZCCI82k</place_id>
 </result>
 <result>
  <type>locality</type>
  <type>political</type>
  <formatted_address>Lisbon, Portugal</formatted_address>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7222524</lat>
    <lng>-9.1393366</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.6913994</lat>
     <lng>-9.2298356</lng>
    </southwest>
    <northeast>
     <lat>38.7958538</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.6913994</lat>
     <lng>-9.2298356</lng>
    </southwest>
    <northeast>
     <lat>38.7958538</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJO_PkYRozGQ0R0DaQ5L3rAAQ</place_id>
 </result>
 <result>
  <type>postal_code</type>
  <formatted_address>1700-111 Lisbon, Portugal</formatted_address>
  <address_component>
   <long_name>1700-111</long_name>
   <short_name>1700-111</short_name>
   <type>postal_code</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Olivais</long_name>
   <short_name>Olivais</short_name>
   <type>administrative_area_level_3</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_2</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7661892</lat>
    <lng>-9.1291486</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.7544060</lat>
     <lng>-9.1483947</lng>
    </southwest>
    <northeast>
     <lat>38.7870843</lat>
     <lng>-9.1239064</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.7544060</lat>
     <lng>-9.1483947</lng>
    </southwest>
    <northeast>
     <lat>38.7870843</lat>
     <lng>-9.1239064</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJS-qk_0UyGQ0RN3v7SZnU9D8</place_id>
 </result>
 <result>
  <type>postal_code_prefix</type>
  <type>postal_code</type>
  <formatted_address>1700, Portugal</formatted_address>
  <address_component>
   <long_name>1700</long_name>
   <short_name>1700</short_name>
   <type>postal_code_prefix</type>
   <type>postal_code</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7600325</lat>
    <lng>-9.1400807</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.7448641</lat>
     <lng>-9.1567550</lng>
    </southwest>
    <northeast>
     <lat>38.7870843</lat>
     <lng>-9.1239064</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.7448641</lat>
     <lng>-9.1567550</lng>
    </southwest>
    <northeast>
     <lat>38.7870843</lat>
     <lng>-9.1239064</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJdVtq_1kyGQ0RYKU7DsHrABw</place_id>
 </result>
 <result>
  <type>administrative_area_level_3</type>
  <type>political</type>
  <formatted_address>Olivais, Portugal</formatted_address>
  <address_component>
   <long_name>Olivais</long_name>
   <short_name>Olivais</short_name>
   <type>administrative_area_level_3</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_2</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7721510</lat>
    <lng>-9.1179465</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.7502229</lat>
     <lng>-9.1483924</lng>
    </southwest>
    <northeast>
     <lat>38.7870963</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.7502229</lat>
     <lng>-9.1483924</lng>
    </southwest>
    <northeast>
     <lat>38.7870963</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJccbEUz4yGQ0RsEKQ5L3rAAU</place_id>
 </result>
 <result>
  <type>administrative_area_level_2</type>
  <type>political</type>
  <formatted_address>Lisbon, Portugal</formatted_address>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_2</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7222986</lat>
    <lng>-9.1393188</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.6913994</lat>
     <lng>-9.2298356</lng>
    </southwest>
    <northeast>
     <lat>38.7958538</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.6913994</lat>
     <lng>-9.2298356</lng>
    </southwest>
    <northeast>
     <lat>38.7958538</lat>
     <lng>-9.0905718</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJMabWPRAzGQ0RRFqNEqmj6AI</place_id>
 </result>
 <result>
  <type>administrative_area_level_1</type>
  <type>political</type>
  <formatted_address>Lisbon, Portugal</formatted_address>
  <address_component>
   <long_name>Lisbon</long_name>
   <short_name>Lisbon</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.7223263</lat>
    <lng>-9.1392714</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>38.6731604</lat>
     <lng>-9.5005266</lng>
    </southwest>
    <northeast>
     <lat>39.3177286</lat>
     <lng>-8.7819208</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.6731604</lat>
     <lng>-9.5005266</lng>
    </southwest>
    <northeast>
     <lat>39.3177286</lat>
     <lng>-8.7819208</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJWxIr4ajVGA0RwCyQ5L3rAAM</place_id>
 </result>
 <result>
  <type>country</type>
  <type>political</type>
  <formatted_address>Portugal</formatted_address>
  <address_component>
   <long_name>Portugal</long_name>
   <short_name>PT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>39.3998720</lat>
    <lng>-8.2244540</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>36.9601772</lat>
     <lng>-9.5171107</lng>
    </southwest>
    <northeast>
     <lat>42.1542048</lat>
     <lng>-6.1902091</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>32.4037400</lat>
     <lng>-31.2752439</lng>
    </southwest>
    <northeast>
     <lat>42.1542048</lat>
     <lng>-6.1902091</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJ1SZCvy0kMgsRQfBOHAlLuCo</place_id>
 </result>
</GeocodeResponse>

Solution

  • The problem was occurring at

    string type = typeElement.FirstOrDefault ().Value;
    

    So I had to test if typeElement.FirstOrDefault () != null

    As below:

        private async Task<string> ReturnCity(string lat, string lon)
        {
            string city = "None";
            string baseUri = string.Format ("http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false", lat, lon);
            HttpClient client = new HttpClient ();
            string response = await client.GetStringAsync (baseUri);
            XElement responseElement = XElement.Parse (response);
            IEnumerable<XElement> statusElement = from st in responseElement.Elements ("status")
                                                   select st;
            if (statusElement.FirstOrDefault () != null) {
                string status = statusElement.FirstOrDefault ().Value;
                if (status.ToLower () == "ok") {
                    IEnumerable<XElement> resultElement = from rs in responseElement.Elements ("result")
                                                          select rs;
                    if (resultElement.FirstOrDefault () != null) {
                        IEnumerable<XElement> addressElement = from ad in resultElement.FirstOrDefault ().Elements ("address_component")
                                                               select ad;
                        foreach (XElement element in addressElement) {
                            IEnumerable<XElement> typeElement = from te in element.Elements ("type")
                                                                select te;
                            if (typeElement.FirstOrDefault () != null) {
                                string type = typeElement.FirstOrDefault ().Value;
                                if (type == "locality") {
                                    IEnumerable<XElement> cityElement = from ln in element.Elements ("long_name")
                                                                       select ln;
                                    city = cityElement.FirstOrDefault ().Value;
                                    return city;
                                }
                            }
                        }
                    }
                }
            }
    
            return city;
        }