×
Namespaces

Variants
Actions

Places Near You with Bing Maps and GeoNames API

From Nokia Developer Wiki
Jump to: navigation, search

This article shows you the way to fetch famous places around you using GeoNames API. After getting the places information we will show them as markers on maps using a Bing Map control.

Note.pngNote: The WP8 version of this article can be accessed at: Places Near You with Nokia Maps and GeoNames API on Windows Phone

SignpostIcon HereMaps 99.png
WP Metro Icon Web.png
SignpostIcon XAML 40.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested with
SDK: Windows Phone SDK 7.1
Devices(s): Nokia Lumia 800
Compatibility
Platform(s):
Windows Phone 7.5
Article
Created: Vaishali Rawat (25 Mar 2013)
Last edited: hamishwillee (19 Jul 2013)

Contents

Introduction

GeoNames API is a large collection of database containing all countries information. This database contains more than eight million places names whose information can be freely downloaded.

Using GeoNames API, we can though fetch hundreds of types of information but in this article we will only fetch one type of information; Places Information. To fetch this information, we will use the Wikipedia API.

Note.pngNote: In this article we will not discuss how to make use of Map control and Bing maps as it's been already shown in many articles on Wiki.

Prerequisites

  • Windows Phone development environment
  • Bing Maps Key
  • Registration at the GeoNames site

Note.pngNote: Please refer this article to obtain a Bing Maps API Key.

References Required

Following references to the DLLs are required in order to implement JSON parsing.

  • System.RunTime.Serialization
  • System.Servicemodel
  • System.Servicemodel.Web

These can be added by Project | References | Add Reference..

Wikipedia API

To make use of Wikipedia API, we will have to make a HTTP server hit at below link http://api.geonames.org/findNearbyWikipediaJSON?
We will pass a few required parameters like our own location, user name etc. In response, we will get the list of near by places in JSON form.

Note.pngNote: One of the parameter i.e. username is compulsory to send with each server request. To know more about username please check this link

Creating UI

In our UI, we will make use of three text blocks and a Bing map control. First TextBlock will have the status message after fetching our device location. Second will have our own latitude value. Last TextBlock will have our longitude value. In our map control, we will show the resultant places with the help of pushpins.

The code in .xaml file is as shown below.

   <!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="0" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height=".05*"/>
<RowDefinition Height=".05*"/>
<RowDefinition Height=".05*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<TextBlock Grid.Row="0" HorizontalAlignment="Left" Name="statusTextBlock" Text="TextBlock" Visibility="Collapsed"/>
<TextBlock Grid.Row="1" HorizontalAlignment="Left" Name="latitudeTextBlock" Text="TextBlock" Visibility="Collapsed"/>
<TextBlock Grid.Row="2" HorizontalAlignment="Left" Name="longitudeTextBlock" Text="TextBlock" Visibility="Collapsed"/>
<my:Map Grid.Row="3" Name="mapControl" CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" Visibility="Collapsed"/>
</Grid>
</Grid>

Initially, all controls visibility is set to Collapsed so that they can be shown only when required.

Code Behind

Files used in JSON parsing

Following file declaration has been used for the JSON parsing.

namespace PlacesNearYou.Data
{
[DataContract]
public class Place
{
[DataMember(Name = "summary")]
public string Summary { get; set; }
 
[DataMember(Name = "distance")]
public string Distance { get; set; }
 
[DataMember(Name = "rank")]
public string Rank { get; set; }
 
[DataMember(Name = "title")]
public string Title { get; set; }
 
[DataMember(Name = "wikipediaUrl")]
public string WikipediaUrl { get; set; }
 
[DataMember(Name = "elevation")]
public string Elevation { get; set; }
 
[DataMember(Name = "lng")]
public string Longitude { get; set; }
 
[DataMember(Name = "feature")]
public string Feature { get; set; }
 
[DataMember(Name = "lang")]
public string Langauge { get; set; }
 
[DataMember(Name = "lat")]
public string Latitude { get; set; }
}
}

Another file declaration used for JSON parsing is:

namespace PlacesNearYou.Data
{
[DataContract]
public class PlacesList
{
[DataMember(Name = "geonames")]
public List<Place> PlaceList { get; set; }
}
}

Making server request

We will start with finding the current location of the phone. For that, we'll make use of GeoCoordinateWatcher API as explained in this article. After successfully fetching the current location of the device (in terms of latitude and longitude), we will start a HTTP request for the GeoNames API. The code snippet is shown below.

    private void startGeoNamesAPICall()
{
try
{
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(AppConstants.baseUri + "&lat=" + currentLatitude + "&lng=" + currentLongitude + "&username=" + AppConstants.strUserName + "&radius=" + AppConstants.strDefaultRadiusForWikiAPI + "&maxRows=" + AppConstants.strDefaultResultRowsForWikiAPI));
httpReq.BeginGetResponse(HTTPWebRequestCallBack, httpReq);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

As shown above, we are passing a few parameters along with the base URL. These parameters are:

  • Our own latitude
  • Our longitude
  • The user name (on behalf of which request is made- its compulsory to provide a registered user name). The username can be registered here. For more info on username, you may check this link.
  • Radius - to determine in how much radius searching will be performed
  • Maximum Rows - how many rows are required as max in the result

Handling server response

The code snippet to handle response is shown below.

 private void HTTPWebRequestCallBack(IAsyncResult result)
{
string strResponse = "";
 
try
{
Dispatcher.BeginInvoke(() =>
{
try
{
HttpWebRequest httpRequest = (HttpWebRequest)result.AsyncState;
WebResponse response = httpRequest.EndGetResponse(result);
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
strResponse = reader.ReadToEnd();
 
parseResponseData(strResponse);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

After converting the WebResponse type data into String, we need to parse it now as it is still in the JSON format. the code snippet for parsing is:

Parsing response data

 private void parseResponseData(String aResponse)
{
placesListObj = new PlacesList();
 
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(aResponse));
DataContractJsonSerializer ser = new DataContractJsonSerializer(placesListObj.GetType());
placesListObj = ser.ReadObject(ms) as PlacesList;
ms.Close();
 
// updating UI
if (placesListObj != null)
{
updateMap(placesListObj);
}
}

Integrating response with UI

In case parsing is done successfully and we've got at least a single record in response, we will show its information on the map using Pushpin(s).

   private void updateMap(PlacesList aWiKIAPIResponse)
{
int totalRecords = aWiKIAPIResponse.PlaceList.Count();
mapControl.CredentialsProvider = new ApplicationIdCredentialsProvider(AppConstants.strBingMapCredentialKey);
mapControl.Visibility = System.Windows.Visibility.Visible;
mapControl.ZoomLevel = 10;
mapControl.ZoomBarVisibility = Visibility.Visible;
 
try
{
for (int index = 0; index < totalRecords; index++)
{
double latitude = Convert.ToDouble(aWiKIAPIResponse.PlaceList[index].Latitude, CultureInfo.InvariantCulture);
double longitude = Convert.ToDouble(aWiKIAPIResponse.PlaceList[index].Longitude, CultureInfo.InvariantCulture);
 
mapControl.Center = new GeoCoordinate(latitude, longitude);
 
Pushpin pushpinObj = new Pushpin();
pushpinObj.Content = aWiKIAPIResponse.PlaceList[index].Title + "\n" + aWiKIAPIResponse.PlaceList[index].Feature;
pushpinObj.Background = new SolidColorBrush(Colors.Red);
pushpinObj.Location = mapControl.Center;
pushpinObj.Opacity = 0.5;
mapControl.Children.Add(pushpinObj);
}
}
catch (Exception)
{
}
}

As shown above, we are only showing the Place's title and it's feature in the pushpin object.

Build and Run

Now you may build the app and try to run it.

References

This page was last modified on 19 July 2013, at 09:48.
273 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×