Part 25: Working with the Geolocator and Geoposition Classes

Source Code: https://aka.ms/absbeginnerdevwp8
PDF Version: https://aka.ms/absbeginnerdevwp8pdf
In this lesson we'll search for Flickr photos near the geocoordinate determined by our phone.
Many of the most popular phone apps have some interaction with web-based services ... so the app allows users to get at their own data that they've stored "in the cloud", or they provide access to data in order to make it available in some fresh new way.
As developers, we can access the web-based services programmatically IF they expose a web API. A web API is usually just an HTTP based method call ... the URL includes the input parameters of the method call, and the web API will return data back in some standard format. Nowadays, that is usually XML or JSON, JavaScript Object Notation.
Flickr is a great example of a web service we can leverage in our apps ... They have a vast amount of image data that we can search via their web-based API. All we need to do is call one of their methods and then parse the data they return to us.
Our game plan in this lesson:
This is a VERY long lesson, but it's crucial because it will serve as a proof of concept that our idea will actually work. We'll see how all the pieces come together and then the rest of the series will be adding improvements and refinements to what we do in this lesson.
Navigate to: http://www.flickr.com/services/api/
This is the home page for Flickr's API.
Before you can take advantage of the API in your app, you'll need to sign up for a developer account.
There should be an obvious Sign Up link somewhere on the top of the page. I won't walk through that process ... it's likely to change over time. I was able to use my existing Yahoo! ID to sign up for a developer account. It's free and easy to get started, and you'll need your own account so that you can get your own API Key.
Most companies exposing APIs over the web want to ensure that developers are complying with their terms of service, or they want to track usage by app to better understand how their APIs are being leveraged. I suppose in extreme cases the company may want to shut down an app that is abusing the service. This is why most require a unique identification for the developer and the app through the use of an API Key. Flickr is no different.
To get an API Key for the AboutMe app, find the "API Key" somewhere on the Flickr API homepage.
This will list all of the API Keys you were granted for your apps. You'll need to use a different API Key for each app you intend to use with Flickr's API.
Ultimately, you want to create a new API Key by using the "Get Another Key" button.
For now, our app will not make any money, or it's not currently commercial but might be in the future, so choose "Apply for a Non-Commercial Key":
They want to learn more about the app you're building. You can copy my text if you want. You'll also need to agree to the terms and such:
When you fill out the form and click the SUBMIT button, you should receive your API Key.
Since I'm (probably) not supposed to legally reveal my key, I've blurred some of it out. Keep the Key and the Secret available. We'll need them later in this lesson.
Back on the main Flickr API page, you see a list of all the web callable APIs available on Flickr. You can literally perform any conceivable operations using Flickr as the backend storage and processor for your photos and create new applications that "mash up" Flickr's functionality with some of your own. That's exactly what we want to do ... combine Flickr's search capability for photos -- specifically searching for photos that were taken geographically in the same place the user of our app.
We want to learn more about the flickr.photos.search API ... how do we call it? What options can we send along to specify geolocation we want to search for?
When you find the API you're looking for (i.e., flickr.photos.search), click the hyperlink to learn more about that web API method.
On this page dedicated to the flickr.photos.search web method, we can see which input parameters are optional and which are required, the purpose / meaning of each parameter, the expected format of the parameter value, and so on.
We also can see a list of error codes returned by the web method to the caller ... this might help us interpret any error codes we receive.
There's also an "API Explorer : flickr.photos.search" link which takes us to a web page where we can experiment and learn how to call that particular web method.
By clicking the "Send" check box and supplying a value, we can see the format that our web method call should take. I'll input the a number of options such as the optional latitude and longitude for the John Hancock Center, and add optional text "observatory":
I'll add an optional radius of "1". I learn that the default "radius_units" are in kilometers, so by adding a "1" I'm saying "search within a 1 kilometer radius of the geocoordinate I'm specifying".
I also will choose to send the output of my query to JSON, the JavaScript Object Notation.
I'll choose the radio button next to "Sign call with no user token".
Once I've added my settings, I'll click the "Call Method..." button.
When I click the "Call Method..." button, a large textbox will appear beneath the button containing sample data in JSON format, as well as the URL that was constructed based on my selected options. Both of these will be important for me in just a moment.
Back in my Visual Studio project, I'll need to prepare for making my first call into the Flickr API. I'll want to appropriately brand the app by changing the app and page titles. I'll just hardcode them this time and not use the resources file. I realize this will limit my app to just English speakers. I can always come back later and change this.
My next changes will be in the ContentPanel.
My goal is to populate the Image control with a single image. Later, I'll add a search results page that can display all the results. For now, I just want to hack something together to figure out how to call into the Flickr search API programmatically and get results. I'll make it work correctly later.
I can find that package on NuGet at: http://nuget.org/packages/Microsoft.Net.Http
NOTE: Since I took this screenshot, this package no longer requires the -Pre argument.
I pay particular attention to the way you install the package using the Package Manager Console: Install-Package Microsoft.Net.Http
To open the Package Manager Console:
This will open the Package Manager Console by default in the bottom area of Visual Studio (unless you docked it somewhere else in a previous session).
You'll type in the install-package command at the Package Manager prompt: Install-Package Microsoft.Net.Http
If all goes smoothly, you'll see the a number of messages appear indicating success:
Now when you look at the Solution Explorer under the References folder, you'll see three new references System.Net.Http.*
Now we should be able to resolve the reference for the HttpClient class. However your mouse cursor over the blue dash under the "H" in HttpClient to reveal a drop-down menu. Choose the: using System.Net.Http;
... option to add a using statement to your MainPage.xaml.cs.
Now I work my way through the process of building a URL to call Flickr's search web API. I'm using that URL from the "API Explorer" as my template, substituting the optional parts like the api_key, license, lat, lon and so on.
Let's run the app (F5) and see what we have so far:
What we get back from Flickr is a string of JSON as we expected.
We will need to convert that string of JSON into something we can use, like CLR types (or rather, classes). There's a little trick for this that I learned from Clint that will create classes that represent the data structures used in the JSON so that we can deserialize it into instances of those classes. Once we have the JSON data into a class hierarchy, we can work with it in C# quite easily.
First, we'll need to grab the actual JSON that has been returned by the web service call to Flickr.
I set a breakpoint on the line of code where we set the ResultTextBlock's Text property to the result from Flickr:
And then I run / debug (F5) the app. When we get to that breakpoint, I hover over the flickrResult variable to see the data. If I click on the little magnifying glass icon next to the data I get a menu that will allow me to see the data in one of several visualization dialog windows:
Choosing "Text Visualizer" will open the Text Visualizer dialog. Here, I can copy all of the JSON on to my clipboard:
... and now that I have that JSON copied to my clipboard, I navigate to:
... and paste the JSON into the large text box on that page, and click the Generate button:
Beneath the Generate button, I get the output: C# classes that match the JSON data structure. Quite awesome!
I click the "Copy" button ...
... and click Ctrl + C to copy the C# code to my clipboard ...
... and paste it (carefully) beneath the Class definition for the MainPage class, but inside the AroundMe namespace like so:
On like 134, I will rename "RootObject" to:
FlickrData
... it's more descriptive of what its purpose is, and I believe in clear names for variables and classes. The result should look like this:
Next, I want to actually deserialize the JSON data into instances of these new classes. To do that, I'll use a third-party but heavily utilized package called Newtonsoft.Json.
I open the Package Manager Console (like I did earlier in this lesson) and type the following: install-package Newtonsoft.Json
... and hit the enter key.
If all goes well, you should get messages indicating success like you see below:
Now, we need to revisit the UpdateMap() method and modify it to actually perform the deserialization:
I run the app (F5) to test:
And it seems to work!
To quickly recap, there were quite a few important takeaways from this lesson ... we learned about the Flickr API which contains hundreds of method calls giving us access to practically every feature of Flickr so we can integrate it in our apps. We learned about getting an API Key and how to call the search API and integrate it into our app. We learned a little about JSON, how to use the json2.csharp.com website to create class definitions that match the JSON we want to work with. We learned about the Newtonsoft.JSON to deserialize the JSON into instances of those classes so we can work with them in C#, and a lot more.
hi,
I want to develop an application which uploads users photographs to a remote server. for eg there is a photo called pic.jpg. now I want to upload this to www.abc.com/images folder. how can I do that??
the url for the json2.csharp should not have the period
RC
@manpreet: You have a few options, but that is a large topic, to large for me to cover here. Either build FTP into your app, or (b) see what you can accomplish with WCF, or ( c ) perhaps you can use an Azure service + API like this article discusses:
http://www.windowsazure.com/en-us/develop/mobile/tutorials/upload-images-to-storage-dotnet/
@rcroeder: Thank you, fixed it in the TEXT version (above).
The image below the following text is wrong:
"... and paste it (carefully) beneath the Class definition for the MainPage class, but inside the AroundMe namespace like so:"
hii,
i want to built an app which can access my geolocation and give me near by ATM machine address and also direction for that ??
how can i do that ???
@wsantosf: Thanks, I'll look into that.
@kushal bhatia: Yikes ... I suppose that's possible, but I have no idea how to go about it. Sorry!
Ok, I'm having an issue that is really driving me crazy and I can't figure it out.
I followed the video and text of this lesson many times over up to the part where we run the emulator at 25 minutes, but my emulator cuts out right before it displays the data I need.
When it cuts out it then points to my
string flickrResult = await client.GetStringAsync(baseUrl);
and then states that the HttpRequestException was unhandled by user code.
@RandomAlec: use a breakpoint at that line, hover over baseUrl and verify that Url works in an actual web browser and you are returning data.
@RandomAlec: betting it may be the flickr API key, verify you are using your own personal one.
I have the same problem as RandomAlec. I have verified that the baseUrl works and that I put my own API Key.
@Clint: My API key is definitely correct, I checked many times over before posting my comment. I will try the Url in an actual web browser to check it.
@fatal1ty: @RandomAlec: are you guys including lat / long? Bob did make a mistake that he points out in the end of part 27 that I caught after the videos were made.
Lat / Long must be rounded to 5 or less decimal points for Flickr's API to work. Bob used the emulator with a location set which rounds to 4 so he never ran into this.
If this doesn't solve your issue, zip up your solution and file a bug at https://absolutebeginner.codeplex.com/workitem/list/basic and I'll take a quick look to see what is happening.
Hi Bob and all others,
I am new to C# and phone developing, using german visual studio.
In the german version of visual studio, I had the problem, that decimal numbers are returned with a comma, insteed of a point.
(Like 41,12334 not 41.12334)
The flickr api always returns invalid value for lat/long.
So I looked around in the internet and found a way which worked
for me.
I did it like this, the rounding I included too :
string str_lat = Math.Round(gpsCoorCenter.Latitude,5).ToString(CultureInfo.InvariantCulture.NumberFormat);
string str_long = Math.Round(gpsCoorCenter.Longitude,5).ToString(CultureInfo.InvariantCulture.NumberFormat);
After I passed this results to the url.
Cheers
Jurgen
@Jurgen: Thank you, awesome tip!
Hi!
Flickr request returns an empty result when uri doesn't contain a text argument. I pass an empty value (text='') then it works.
Thanks!
Thanks Mr.Bob for this awesome tutorial .
it works when i put "&text=a" on the url or any letter ..
@Bob thank you for great tutorial!<br>Does anyone get same error as me during package installation ?Install failed. Rolling back...
Install-Package : Failed to add reference to 'System.IO'.
At line:1 char:1
+ Install-Package Microsoft.Net.Http
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Install-Package], InvalidOperationException
+ FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand
@Tomek: My gut says you need to update Nuget. This post has the steps to do it. https://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners/Part-17-Introducing-the-Coding4Fun-Toolkit
hi,
I want to develop an application which uploads users photographs to a Flickr.com.
@Heena Buddhadev: awesome! check out http://www.flickr.com/services/api/ for how to use their APIs.
@Clint, Thank you it helped!
FYI you can paste json as C# directly in VS: https://blogs.msdn.com/b/webdev/archive/2012/12/18/paste-json-as-classes-in-asp-net-and-web-tools-2012-2-rc.aspx
Hi Bob,
i am playing with the json web services and i got an issue with https certificate. My server lets say, something.net is using something.com's certificate and i have to ignore and retrieve the data. Is there any way to do that in windows phone 8?
@Sheshu: we're supporting only the lessons here, for that question, head over to the forums on https://dev.windowsphone.com or www.stackoverflow.com
Hi,
I am getting below exception.
"A first chance exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.ni.dll
If there is a handler for this exception, the program may be safely continued."
if ,my key seems to be alright. if I use the URl to the explorer then it seems to work:" asking me to save or open rest.json...?" .
I also used the method UpdateMap() as it is from the sample solution and changed my key. I see the same issue.
any clue here please?
Sanjay
adding additional information:
the above exception happens during the execution of the line:
string flickrResult = await client.GetStringAsync(baseUrl);
Thanks Bob, Clint and Larry for this amazing video series :) I hope I'm not asking a silly question.. but how did you come up with URL construction? Thanks!
HI Client,
Thanks for saying some this else is happening.
really the internet connection in the emulator was missing. I shifted to new place for winter vacation but I didn't set up the internet connection.
Now it works.
Sanjay
Hi Clint,
I get 404 Exception when tried to connect to flickr (the same as for example RandomAlec). However, I went mad and restarted my PC, and after that it worked. Any clue what happened? I did not change anything.
Another issue, the Replace(",","%2C") method is not working, my license string contains the same commas, so I had to hard-code them. Don't know really why.
Shame on me, the Replace method works well. Forget that.
Sir,
I have almost tried everything. But Flickr Image is not displaying in image box. Please help me.
Problem Solved. I was using flicker instead of flickr in photoUrl
hi,
your code run first time and when run it again throw exception
I'm watched last part of video and problem not solved and I have the same Bug :'(
Excellent tutorials, I guess you could also use the JSON output of Flickr to generate the class with Json2csharp. But my main question is why don't you use sperate folders. I.e. A folder for the classes (like the FlickrData-class) or even better a sperate project for the Flickr classes and methods, so you can use it in some other projects later. Or is this out of scope? Just wondering.
@BobTabor:I had the same issue as @Jurgen, but fixed it a by hardcoding the CultureInfo in formatting of the base URL, like so:
var baseUrl = string.Format(new CultureInfo("en-US"), url, etcetc
@BobTabor: These tutorials are awesome. I know its a year later, but I'm really struggling. I have a JSON string with lists inside lists inside lists. and I'm unable to dig down through these layers with your method of deserialization. I can only get to the second layer. I tried using dictionaries and expandoObject (which seems to give the right structure) but I can't get at the data. Is there an easy way to dig maybe 4 arrays down?
I was not stipulating which branch to go down and so it was confused.
System.Diagnostics.Debug.WriteLine(apiData.jobsByDateList[0].jobsList[0].interestLevel);
I was trying to get in using
System.Diagnostics.Debug.WriteLine(apiData.jobsByDateList.jobsList.interestLevel);
like your example and intellisense was freaking out.
With the [0] I'm now able to drill in just fine and don't need the expandoobject. Just needed to sleep on it. :-)
Hi Bob,
I want to search some animated gif images from Flickr. Because uploaded images had been resized and converted, they cannot animate. Only orignial size images can animate. But I don't know how to get the original size images in the json result. How can I do this?
Thanks
hi Bob,
I am facing an issue regarding an exception 404. I followed alll of your instructions but when i run the app it throws following Exception :-
"An exception of type 'System.Net.Http.HttpRequestException' occurred in mscorlib.ni.dll but was not handled in user code
Additional information: Response status code does not indicate success: 404 ()."
i am stuck here for nearly a week. Kindly help me with this error
Image is not getting displayed. I 've put a breakpoint on setting imagesource line and checked the uri in webbrowser. It displayed the image. But in app its not getting displayed
Could anyone please help me to show a POINTER(Push Pin) at the location on a map using map control/maps task ?