September 2, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Understanding Search Extensibility for Windows Phone 8

  • July 12, 2013
  • By Vipul Patel
  • Send Email »
  • More Articles »

Introduction

Quick cards are part of Windows Phone search results that collect useful information and present it in a single easy-to-use place. For example, if you are searching for a movie on Windows Phone, you will find related information about the movie (like show times, movie cast details, etc.)

Windows Phone 8 allows applications to extend the search experience of Windows Phone by building upon the information contained in the quick cards. 

Windows Phone supports four types of quick cards: places (listed under local), products (listed under products heading under web), movies (listed under "Movies near" under web) and events (listed under "see+do" in Local Scout).

Every quick card displays content like photos, descriptions, ratings, reviews, movie duration, etc. about the search result. Additionally, every quick card contains a pivot called app, which is reserved for applications that extend the search experience. Apps can be built, which provide a richer experience to the users based on the information on the quick card.

Search Extensibility Developer Basics

To provide search extensibility, a Windows Phone 8 application needs to declare the extensions relevant to the application in WMAppManifest.xml.  For example, to extend the search experience around movies, the "Bing_Movies and "Bing_Products_Movies" extensions can be used.

The application also needs an Extras.xml, which contains details about the APP Title (for Windows Phone 7.1) and Captions about the extensions.

Lastly, the application needs an application page to receive a deep link URI from the search result quick card.

Hands On

For our example, we will build an application that extends search functionality for movies.

Start Visual Studio 2012 and create a new Windows Phone 8 project titled WindowsPhoneSearchExtensionDemo.

New Windows Phone 8 Project
New Windows Phone 8 Project

When prompted, select Windows Phone OS 8.0 as the target OS.

Target Windows Phone OS Version
Target Windows Phone OS Version

Right click on WMAppManifest.xml and select to View Code.

WMAppManifest.xml
WMAppManifest.xml

Next, we will register search extensions for movies. For movies, which are currently playing in cinemas,  the extension is “Bing_Movies”; for those movies that aren’t, the extension is “Bing_Products_Movies”.

A complete list of available extensions for registration is available at http://msdn.microsoft.com/en-US/library/windowsphone/develop/hh202958(v=vs.105).aspx

<?xml version="1.0" encoding="utf-8"?>
 
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
  <DefaultLanguage xmlns="" code="en-US"/>
  <App xmlns="" ProductID="{a3bf312b-e2e9-481f-8a4f-17031d2239d4}" Title="WindowsPhoneSearchExtensionDemo" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"  Author="WindowsPhoneSearchExtensionDemo author" Description="Sample description" Publisher="WindowsPhoneSearchExtensionDemo" PublisherID="{1cd3778b-3df5-415c-9a0e-6ac19bf03788}">
    <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_MEDIALIB_AUDIO"/>
      <Capability Name="ID_CAP_MEDIALIB_PLAYBACK"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
    </Capabilities>
    <Tasks>
      <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/>
    </Tasks>
    <Tokens>
      <PrimaryToken TokenID="WindowsPhoneSearchExtensionDemoToken" TaskName="_default">
        <TemplateFlip>
          <SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
          <Count>0</Count>
          <BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
          <Title>WindowsPhoneSearchExtensionDemo</Title>
          <BackContent></BackContent>
          <BackBackgroundImageURI></BackBackgroundImageURI>
          <BackTitle></BackTitle>
          <DeviceLockImageURI></DeviceLockImageURI>
          <HasLarge></HasLarge>
        </TemplateFlip>
      </PrimaryToken>
    </Tokens>
    <Extensions>
      <Extension
        ExtensionName="Bing_Movies"
        ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}"
        TaskID="_default"
        ExtraFile="Extensions\\Extras.xml"
        />
    <Extension
        ExtensionName="Bing_Products_Movies"
        ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}"
        TaskID="_default"
        ExtraFile="Extensions\\Extras.xml"
        />
    </Extensions>
    <ScreenResolutions>
      <ScreenResolution Name="ID_RESOLUTION_WVGA"/>
      <ScreenResolution Name="ID_RESOLUTION_WXGA"/>
      <ScreenResolution Name="ID_RESOLUTION_HD720P"/>
    </ScreenResolutions>
  </App>
</Deployment>

Create a new folder called “Extensions” and create a new XML file in that folder called Extras.xml.

Create Extras.xml
Create Extras.xml

In this Extras.xml, we will declare the captions for our extensions.

We will caption the “Bing_Movies” extension as “Movie Details” and the “Bing_Product_Movies” extension as “Other Movie Details”.

The contents of our Extras.xml is below.

<?xml version="1.0" encoding="utf-8" ?>
<ExtrasInfo>
  <!-- Search-related captions -->
  <Consumer ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}">
    <!-- Movies caption -->
    <ExtensionInfo>
      <Extensions>
        <ExtensionName>Bing_Movies</ExtensionName>
      </Extensions>
      <CaptionString>
        <default>Movie Details</default>
      </CaptionString>
    </ExtensionInfo>
    <!-- Product Movies caption -->
    <ExtensionInfo>
      <Extensions>
        <ExtensionName>Bing_Products_Movies</ExtensionName>
      </Extensions>
      <CaptionString>
        <default>Other Movie Details</default>
      </CaptionString>
    </ExtensionInfo>
  </Consumer>
</ExtrasInfo>

Finally, we will build the mapping the URI from the quick card.

We will begin by creating MyURIMapper class.

Create a new class MyURIMapper in a file called MyURIMapper.cs (we will need to create this file).

In this class, you will declare a static string for the movie page.

public static string moviePage = "MoviePage.xaml";

You will also implement an override for the MapUri API. Here, we will check if the launch URI contains Bing_Movies and will then parse the URI to extract the MovieName, Release Date and Category, which we will then use to compose the deep URI to our movie landing page, MoviePage.xaml.

public override Uri MapUri(Uri uri)
        {
            string tempUri = uri.ToString();
            if (tempUri.Contains("/SearchExtras"))
            {
                tempUri = HttpUtility.UrlDecode(tempUri);
                if (tempUri.Contains("Bing_Movies"))
                {
                    string MovieNameValue = GetURIParameterValue("MovieName=", tempUri);
                    string ReleaseDateValue = GetURIParameterValue("ReleaseDate=", tempUri);
                    string CategoryValue = GetURIParameterValue("Category=", tempUri);
 
                    string NewURI = String.Format("/{0}?MovieName={1}&ReleaseDate={2}&Category={3}",
                                    moviePage, MovieNameValue, ReleaseDateValue, CategoryValue);
 
                    return new Uri(NewURI, UriKind.Relative);
 
                }
 
                if (tempUri.Contains("Bing_Products_Movies"))
                {
                    string MovieNameValue = GetURIParameterValue("MovieName=", tempUri);
                    string CategoryValue = GetURIParameterValue("Category=", tempUri);
 
                    string NewURI = String.Format("/{0}?MovieName={1}&Category={2}",
                                    moviePage, MovieNameValue, CategoryValue);
 
                    return new Uri(NewURI, UriKind.Relative);
 
                }
 
 
            }

We will need a helper method to extract the parameter positions, which will be implemented in GetURIParameterValue and FindNextParameter methods.

private string GetURIParameterValue(string parameteridentifier, string uri)
        {
            string myValue = "";
            if (uri.Contains(parameteridentifier))
            {
                string subUri = uri.Substring(uri.LastIndexOf(parameteridentifier)).Replace(parameteridentifier, "");
 
                int nextParameterPosition = FindNextParameter(subUri);
                if (nextParameterPosition < int.MaxValue)
                {
                    myValue = subUri.Substring(0, nextParameterPosition);
                }
                else
                {
                    myValue = subUri;
                }
                myValue = HttpUtility.UrlEncode(myValue);
            }
            return myValue;
        }
 
 
        private int FindNextParameter(string subUri)
        {
            int lowestPosition = int.MaxValue;
            int tempPosition;
            tempPosition = subUri.IndexOf("&Category");
            if ((tempPosition > -1) && (tempPosition < lowestPosition)) lowestPosition = tempPosition;
 
            tempPosition = subUri.IndexOf("&ReleaseDate");
            if ((tempPosition > -1) && (tempPosition < lowestPosition)) lowestPosition = tempPosition;
 
            tempPosition = subUri.IndexOf("?MovieName");
            if ((tempPosition > -1) && (tempPosition < lowestPosition)) lowestPosition = tempPosition;
 
            return lowestPosition;
        }

Next, we will wire our Custom URI Mapper as the root frame of our application.

Add the following line in the InitializePhoneApplication method in App.xaml.cs.

private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;
 
            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;
 
            RootFrame.UriMapper = new MyURIMapper();
            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;
 
            // Handle reset requests for clearing the backstack
            RootFrame.Navigated += CheckForResetNavigation;
 
            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

Finally,  we will create our landing page for the movies, MoviePage.xaml.

Create the Landing Page
Create the Landing Page

Add  three textBlocks and three textboxes, one each for movie name, release date, and category.

Next, in the page_loaded event, we will parse the query string and extract the information. The query string is available in the navigation context of the page.

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.NavigationContext.QueryString != null)
            {
                IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;
                this.textBoxMovieName.Text = queryStrings["MovieName"];
                DateTime releaseDate = DateTime.FromFileTimeUtc(long.Parse(queryStrings["ReleaseDate"]));
                this.textBoxReleaseDate.Text = releaseDate.ToShortDateString();
                this.textBoxCategory.Text = queryStrings["Category"];
            }
        }
 

Now, our application is complete.

If you are having trouble following along, you can download sample code from here.

Running Our Application

Run our application and search for “world war z”.

Run the Application
Run the Application

Scroll down on the page, until you see the quick card for the movie. Once you see, click the quick card.

Click the Quick Card
Click the Quick Card

You will be brought to the “about” view for the movie.

About View
About View

Scroll right until you are in the appview. Here you will see that our application is listed under the apps list. Click on our application name to launch our application to see what information it provides.

Click to Launch
Click to Launch

Once our application is launched, you will see that it shows the following information about the movie.

Movie Information
Movie Information

You can see that World War Z was released on 6/21/2013 and the category is Bing_Movies.

Search extension can be applied to show more details about the movie, for example, to show rotten tomatoes of the movie, links to editorial reviews for the movie, etc.

Summary

In this article, we learned how to build Windows Phone 8 applications that provide search extensibility. I hope you have found this information useful.

About the Author

Vipul Patel is a Program Manager currently working at Amazon Corporation. He has formerly worked at Microsoft in the Lync team and in the .NET team (in the Base Class libraries and the Debugging and Profiling team). He can be reached at vipul.patel@hotmail.com


Tags: search, application, Windows Phone 8




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel