(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

geoGallery, a Window Phone 7 sample

(8 votes)
Levente Mihály
>
Levente Mihály
Joined Apr 27, 2010
Articles:   7
Comments:   16
More Articles
2 comments   /   posted on May 10, 2010
Tags:   window-phone-7 , geogallery , picasa , levente-mihály
Categories:   Windows Phone
Recently I had some time to play with the new Windows Phone 7 Developer Tools CTP. I have created a sample application (called „geoGallery”), you can watch the demo video and download the code. It’s a Gallery application, but to give it a little twist, it gets the pictures from Google Picasa based on your location!
Record your screencast online

Download source code

Now I’m going to guide you through the code, focusing on the Phone specific features, methods and problems I experienced.

If you haven’t done it yet, you can download the new „April Refresh” CTP, it is now compatible with Visual Studio 2010 RTM.

 

Structure of the sample application

  • MainPage: a label with the current city and a listbox for the categories. Once the city is resolved, the listbox becomes enabled.
  • ResultPage: a listbox containing the images of the Picasa query.
  • DetailsPage: image with title and description.

Points of interests are:

NavigationFramework

I started writing the application using the Windows Phone List Application project template. This creates a project with a main page and a details page. It’s a bit like the Silverlight Navigation Application template.

listproject listproject1

It also gives us a sample ViewModel but what I most like is the nice navigation animations pre-setted. When the category is selected, we don’t navigate yet, just start the navigation storyboard, and in the event the storyboard is completed we make the navigation.

 // Capture selected item data
 selectedItem = (sender as ListBox).SelectedItem as Category;
  
 if (_selectedItem != null)
 {
    // Start page transition animation
    PageTransitionList.Begin();
 }
 ...
 private void PageTransitionList_Completed(object sender, EventArgs e)
 {
     // pass the selected category item in the querystring
     Category selectedCategory = _selectedItem as Category;
     NavigationService.Navigate(new Uri(String.Format("/ResultPage.xaml?category={0}&city={1}", _selectedItem.Title, textBlockListTitle.Text), UriKind.Relative));            
 }

But there are some differences between Silverlight’s and the Phone’s navigation framework, the Phone’s a bit simpler:

navfw

Another difference is the missing NavigationCache property. In Silverlight I have often used this property for keeping the state of the page. If it’s enabled the page state is saved to the memory, this means the constructor won’t be called again for the page, so the ViewModel won’t be re-created. Obviously by hiding this NavigationCache property (and set to “False” as default) is a decision made by Microsoft to force developers to save resources.

In my case, it meant that I had to come up with a workaround for the ResultPage’s state. Since re-initializing the ResultPage, making the query again is clearly a no-go, I cached the ResultViewModel in a static variable in the App class.

Location Services

Every Windows Phone 7 device will include a GPS receiver. When geoGallery starts it tries to resolve the location of the phone, and from that data, the current city. This means a one-time location query, with low accuracy. Let’s see how to do that!

First, we need to reference the System.Device.Location assembly. Then create a GeoCoordinateWatcher instance, and initialize it. We need to sign up for the StatusChanged event. I set the Accuracy to Low, since I only need the City now. WinPhone7 can obtain the location information also from cellular info or from the Wi-Fi network, which usees less power than the GPS (but not as accurate). If the Status is “Ready” we can stop GeoCoordinateWatcher, again, to save power. If you want to follow the position, you must sign up for the PositionChanged event. Once we get the location, we can start resolving the address. For this, we can use the CivicAddressResolver class.

 {
     // setup mixdemohelper
     LasVegasLocationData.Setup();
     // init geoWatcher, resolver
     geoWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Low);
     geoWatcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(geoWatcher_StatusChanged);
     resolver = new CivicAddressResolver();
     resolver.ResolveAddressCompleted += new EventHandler<ResolveAddressCompletedEventArgs>(resolver_ResolveAddressCompleted);
     geoWatcher.Start();
 }
 void geoWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
 {
     // check if position is resolved
     Deployment.Current.Dispatcher.BeginInvoke(() =>
     {
          // show status from some feedback to user
          CityInfo = e.Status.ToString();
  
          // if position resolved start address resolver
          if (e.Status == GeoPositionStatus.Ready)
          {
              resolver.ResolveAddressAsync(geoWatcher.Position.Location);
              geoWatcher.StatusChanged -= geoWatcher_StatusChanged;
              geoWatcher.Stop();
          }
     });
  
 }

Note that both GeoCoordinateWatcher and CivicAddressResolver work in a different thread, so we need to use the Dispatch object to reach the UI thread. When I did that, the Visual Studio designer always crashed, the resolution was of course to start the location service only if we are not in design mode (you can use the DesignerProperties.IsInDesignTool property).

Since the emulator can’t use the System.Device.Location assembly, I used Peter Torr’s mock location APIs, so don’t be surprised if you always end up in Vegas! The trick is to switch the System.Device.Location namespace to MixDemoHelpers.Location. Because the mock API is not complete yet, I had to extend its CivicAddress class with the “City” property.

UI and Design

Styles

The project template comes with a few pre-defined styles and colors matching the Metro theme. If you open up the App.xaml you will see the pre-defined colors and brushes. Actually, these are only for the VS/Blend designer. If you delete them from the source, the app will still run, furthermore, if you go to the phone settings and change the theme, your application will reflect the changes. Here’s a picture of the sample with the Light/Green theme.

geogalleryTheme

Orientation

Another phone specific goal is to handle the orientation. It’s fairly easy, for each page we can set the SupportedOrientations property. For the ResultPage and for the DetailsPage I enabled both the Portrait and the Landscape mode. Once the phone rotates the content automatically rotates too. But sometimes this is not exactly what we want…

In landscape mode the images’ Listbox is not very usable. I replaced this with a horizontal Listbox, here’s the template for that:

 <ListBox.ItemsPanel>
     <ItemsPanelTemplate >
         <StackPanel Orientation="Horizontal"
                     HorizontalAlignment="Center"
                     VerticalAlignment="Center"
                    />
     </ItemsPanelTemplate>
 </ListBox.ItemsPanel>

I’m switching visibility of the two listboxes in the OnOrientationChanged eventhandler, and in the OnNavigatedTo eventhandler.

For the DetailsPage, in portrait-mode I’m hiding the title and description, this way getting something kind of a full-screen mode.

Loading

On the ResultPage I put a simple loading animation to give the user some response while waiting for the Picasa response. I looked hard, but couldn’t find any loading animations in existing videos (everything is so snappy), but I think it goes well with the Metro theme.

loading

Google Picasa API

For retrieving the images I chose Google Picasa. I didn’t want to bother with api-keys, so Picasa seemed a good choice. You can check the Picasa API here.

The community search feed looks like this: http://picasaweb.google.com/data/feed/projection/all?kind=photo&q=searchTerm

From the parameters I included in the max-results, and the parameter “l”. The latter means that the query searches for photos in the given named location, in our case the city.

I parsed the response with simply awesome LinqToXML, selecting the image url, title, summary, and from the thumbnails the last one’s url, because that one is the biggest.

 // parse result
 XDocument xdoc = XDocument.Parse(e.Result);
 // namespaces
 var ns = "{http://www.w3.org/2005/Atom}";
 var media = "{http://search.yahoo.com/mrss/}";
  
 // parsing
 try
 {
      List<PicasaPic> resultlist =
           (from entry in xdoc.Descendants(ns + "entry")
           select new PicasaPic()
           {
               ImgSrc = entry.Element(ns + "content").Attribute("src").Value,
               Title = entry.Element(ns + "title").Value,
               Summary = entry.Element(ns + "summary").Value,
               ThumbSrc = entry.Elements(media + "group").Elements(media + "thumbnail").Last().Attribute("url").Value
           }).ToList();
  
     resultlist.ForEach(item => ResultPics.Add(item));
 }

Summary

As you can see, developing for Windows Phone 7 is easy, with some Silverlight knowledge everybody can start writing their own applications (and I mean it, since the tools are free for all). The differences of phone’s “super-subset” of Silverlight 3 are reasonable, small and easy to adopt.

I hope you liked my sample application, and I hope it’s useful for starters.


Subscribe

Comments

  • -_-

    RE: geoGallery, a WinPhone7 sample


    posted by JDM on Dec 09, 2010 02:10
    CivicAddressResolver is not implemented in the current release of Silverlight for WinPhone 7.
  • wildfox

    RE: geoGallery, a WinPhone7 sample


    posted by wildfox on Dec 09, 2010 13:00

    True, the demo created for the CTP. You can use Bing Maps reverse geocode service in the meantime: Developing a Silverlight Application Using Bing Maps SOAP Services

Add Comment

Login to comment:
  *      *