Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Mango | Day #22: App Connect

Written in

by

Day22-AppConnectDay21-SocketsDay20-RingtonesDay19-AddingTiltEffectsDay18-ExpressionBlendSampleData

This article is Day #22 in a series called 31 Days of Mango, and is written by guest author Matt Eland.  Matt can be reached on Twitter at @integerman.

What is App Connect?

Windows Phone Mango introduces a multitude of fantastic improvements to the already great Windows Phone operating system. Among these enhancements are number of improvements to the Bing search engine on the phone. While many of these features such as visual search and turn by turn directions are intended for customers, Microsoft also introduced a few features aimed at allowing developers to integrate apps into the search results either via Instant Answers, a way of highlighting apps relevant to specific searches, or via a new feature in Mango called Quick Cards.

Quick Cards are items that appear in certain searches that allow users to find out more about certain products, locations, or movies within Bing. Pictured below is an example of search results that include Quick Cards for several books matching the user’s search:

clip_image002

Clicking on one of these items navigates you to that product’s Quick Card which allows you to find more information on a product in a centralized location as pictured below:

clip_image004

App Connect is another new feature in Windows Phone Mango that allows apps to be listed on the apps pivot item on Quick Cards that are relevant to an app’s subject matter. From there, the user can click and launch the app and be met with an app launch experience that can be custom tailored to the Quick Card the user just came from.

It’s important to note that presently only the United States supports product and movie Quick Cards though place Quick Cards are more widely available. Despite this present limitation we will also touch on localizing search result text.

See http://msdn.microsoft.com/en-us/library/hh202957(v=VS.92).aspx#BKMK_AppConnect for a more detailed and up-to-date list on the types of Quick Cards that are supported.

Similar to Quick Cards, developers can also have their apps be aware of scenarios where they are launched as by Bing Instant Answers, another Mango improvement to Bing search. Bing Instant Answers allows Bing to feature certain apps that it thinks are highly relevant to a specific search.

For this article we will be creating an app that allows you to quickly search for a book on an online retailer’s site by taking advantage of search extensibility integration for Quick Cards for books and magazines and providing a customized experience if it was launched from Bing Instant Answers.

Getting started with search extensibility

Setting up your app to take advantage of App Connect is relatively easy though there are a number of steps you’ll need to follow in order to get things working.

We’ll start by creating a new Visual Studio Windows Phone Application project targeting Windows Phone 7.1.

Registering search extensions

In order for Windows Phone to know that your app supports App Connect, you need to add an entry to the manifest file telling the phone what search extensions the app supports. This is important and should only include product types that are relevant to your application.

Expand the properties node of the project file and go into WMAppManifest.xml. This is the phone’s application manifest for the marketplace and defines all relevant information for your application. You’ll need to add a new node inside of the App element as illustrated in the following file:

<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.1">
    <App ="" >
        <IconPath IsRelative="true" IsResource="false">ApplicationIcon.jpg</IconPath>
        <Capabilities></Capabilities>
        <Tasks>
            <DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>
        </Tasks>
        <Tokens></Tokens>
        <Extensions>
            <!– Beta extension, for development and testing only –>
            <Extension ExtensionName="Products"
            ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}"
            TaskID="_default"
            ExtraFile="Extensions/Extras.xml" />
            <!– Production extensions, for submission to Marketplace –>
            <Extension ExtensionName="Bing_Products_Books_and_Magazines"
            ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}"
            TaskID="_default"
            ExtraFile="Extensions/Extras.xml" />
        </Extensions>
    </App>
</Deployment>
 

The important aspect of this is the two Extension elements. ExtensionName identifies which Quick Card the extension supports integration with. See http://msdn.microsoft.com/en-us/library/hh202958(v=VS.92) for a complete list of available Quick Cards.

The emulator handles App Connect differently than the final version Mango that runs on phone. In the emulator all product Quick Cards have a category of “Products” instead of the more specific individual ExtensionNames. That is to say that if we registered our app to support books and magazines by using the “Bing_Products_Books_and_Magazines” ExtensionName, our app would show up as supported for a book Quick Card on the device but not on the emulator and if we registered as only supporting the “Products” category, the app would appear to work fine in the emulator but would not work properly on actual devices. Because of this you’ll want to support both the broad “Products” category as well as any specific categories you may want to handle by defining multiple Extension elements.

The other fields in the Extension element are relatively simple to deal with: ConsumerID identifies search extensibility as the feature the extension maps to and should not be changed. TaskID specifies the task that should be launched when the extension is triggered. ExtraFile tells the app where to look for the extra data needed to support search integration and must point to Extensions/Extras.xml or App Connect will not work.

Configuring extra data needed by App Connect

Since our project doesn’t contain the Extensions/Extras.xml we referenced in the two extensions we registered we’ll have to create it. Right click on the project in the solution explorer and click “Add -> New Folder”, rename the folder to “Extensions”, right click that folder and select “Add -> New Item”. Select XML File from the list and name it Extras.xml. The name and path of this file must be exact or search extensions will not function properly.

clip_image006

You should now have an Extras.xml file in the Extensions folder. From here we’ll need to add an ExtrasInfo node to the xml file that defines how the app behaves with the extensions we registered.

<ExtrasInfo>
    <AppTitle>
        <!– Neutral language application title. –>
        <default>Book Helper</default>
        <!– Localized titles –>
        <es-ES>Libro Helper</es-ES>
        <fr-FR>Livre Helper</fr-FR>
        <zh-CN></zh-CN>
    </AppTitle>
    <Consumer ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}">
        <ExtensionInfo>
            <Extensions>
                <!– Corresponding product extension for books –>
                <ExtensionName>Bing_Products_Books_and_Magazines</ExtensionName>
                <!– Beta extension, for all products. –>
                <ExtensionName>Products</ExtensionName>
            </Extensions>
            <CaptionString>
                <!– Neutral language caption –>
                <default>Search vendors for books and eBooks</default>
                <!– Localized captions –>
                <es-ES>Bsqueda de libros y libros electrnicos de varios proveedores</es-ES>
                <fr-FR>Recherche de livres et eBooks provenant de divers fournisseurs</fr-FR>
                <zh-CN></zh-CN>
            </CaptionString>
        </ExtensionInfo>
    </Consumer>
</ExtrasInfo>
 

The AppTitle element and its children tell Windows Phone what to call our application (and provide some localized strings for different locales). The default node inside of this is used if a locale-specific string cannot be found and should represent the app’s title in the assembly’s neutral language. Additional nodes can be added with names matching the culture code that the localized string is for. For example, es-ES in this example indicates the string used in Spanish language settings.

The Consumer node has a ConsumerID that matches the ConsumerIDs we registered in the WMAppManifest.xml file earlier. Inside of this node is an ExtensionInfo node with an Extensions node that contains ExtensionName elements that define the extensions we said we supported.

The CaptionString element defines the message used next to the search extension’s tile and is localized the same way the AppTitle element is. An example of this app showing up as a search extension is pictured below:

clip_image008

Note that the application’s icon is used for this image and the background could be either light or dark depending on the theme. Consequently, transparency on app icons should not be used when App Connect integration is present. Additionally, the pivot item for App Connect on Quick Cards in the emulator says “extras” while in actual Mango devices this pivot item is labeled “apps”.

If you need to specify different captions for different types of products, you can do so by declaring multiple ExtensionInfo elements and using some ExtensionName elements in one ExtensionInfo element and others in another as long as all ExtensionNames you say your app supports are represented in an ExtensionInfo.

Setting up URI mapping

When a user enters the app using App Connect the runtime will attempt to navigate to the /SearchExtras URI. In order to support this entry point we’ll need to set up some URI mappings to redirect traffic to the appropriate page. To do this, we’ll define a UriMapper resource in the Application’s resources collection by going into App.xaml and adding the following resource to Application.Resources:

<Application.Resources>
    <nav:UriMapper x:Key="UriMapper" xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone">
        <nav:UriMapper.UriMappings>
            <nav:UriMapping Uri="/SearchExtras" MappedUri="/MainPage.xaml" />
        </nav:UriMapper.UriMappings>
    </nav:UriMapper>
</Application.Resources>
 

Defining this resource isn’t enough. We need to tell the app to find and use this UriMapper for resolving requests. We do this by adding the following code to the constructor in App.xaml.cs:

// Enable URI mapping for Search Extras deep link URIs

RootFrame.UriMapper = Resources["UriMapper"] as UriMapper;
 

This will correctly map all incoming App Connect traffic to navigate to the MainPage once our application uses. If we wanted to we could specify a specific item details page in the MappedUri property that is specific to App Connect but for the purposes of this example, this will suffice.

Taking advantage of App Connect integration

At this point if you run your application in the emulator and then go to Bing search on the device using the search key, you should see your application listed on the extras pivot for a product’s Quick Card – provided you registered your app as supporting Products – individual product type mappings do not work for the emulator but will work on your actual device (and vice versa – registering as supporting the broad category of products does not work on actual devices).

Unfortunately, our app doesn’t actually do anything with the data provided by App Connect yet. To fix this, let’s start by defining our user interface. Go into MainPage.xaml and replace the Grid named LayoutRoot and all of its children with the following XAML:

<Grid Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Margin="12,17,0,28">
        <TextBlock Text="BOOK HELPER" Style="{StaticResource PhoneTextNormalStyle}" />
        <TextBlock Text="Welcome" x:Name="lblPageTitle" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />
    </StackPanel>
    <ScrollViewer Margin="12,0,12,0" Grid.Row="1">
        <StackPanel>
            <TextBlock TextWrapping="Wrap" x:Name="lblBookTitle" Visibility="Collapsed" Style="{StaticResource PhoneTextLargeStyle}" Text="Book title goes here" />
            <TextBlock TextWrapping="Wrap" x:Name="lblNoSearch" Text="To use this product, use your device’s search functions to look for a book and then select this app from the apps section." Style="{StaticResource PhoneTextNormalStyle}" />
            <HyperlinkButton HorizontalContentAlignment="Left" Foreground="{StaticResource PhoneAccentBrush}" Margin="{StaticResource PhoneVerticalMargin}" Content="Search Amazon" Click="HandleSearchAmazonBooks" />
            <HyperlinkButton HorizontalContentAlignment="Left" Foreground="{StaticResource PhoneAccentBrush}" Margin="{StaticResource PhoneVerticalMargin}" Content="Search Barnes and Noble" Click="HandleSearchBarnesAndNoble" />
        </StackPanel>
    </ScrollViewer>
</Grid>
 

This defines a user interface that will be able to function either as a stand-alone app (in case of a normal app launch) or serve as a details page if the application is launched using App Connect. By default, the application will look like the following image:

clip_image010

Handling Query Parameters

Obviously, we’d like to be able to do something special if we launched the app from App Connect on a Quick Card. Thankfully, when entering a page via App Connect, the navigation context of the page contains two query string parameters that can help us identify basic information on the Quick Card that launched the application. The ProductName query string argument will contain the name of the product that is associated with the Quick Card the user just viewed and the Category argument will be the ExtensionName that is associated with that Quick Card.

It is important to wait for the page to load before checking for query string parameters since the NavigationContext will not be available until loading is complete.

While this is fairly basic information, it is still useful for applications that need to pre-populate fields or controls with product names or for pages that need to be flexible enough to handle multiple types of products. Bear in mind that for debugging purposes Category will always be “Products” in the emulator but will have the correct values when run on an actual device.

For our sample app, we’ll have the page display the product name in the page if we came in to the app through App Connect, but leave the existing user interface if this is handling a standard launch. Because the app launch entry point and the search extras entry point use the same page for our demo it is important to check for the existence of the query string arguments before trying to use them.

Here is the modified MainPage.xaml.cs that includes logic for parsing the query string parameters and handling hyperlink clicks:

public partial class MainPage : PhoneApplicationPage
{
    private string _book;
    // Constructor
    public MainPage()
    {
        InitializeComponent();
        // We need to wait until loaded before checking NavigationContext
        Loaded += HandleLoaded;
    }

    private void HandleLoaded(object sender, RoutedEventArgs e)
    {
        // Determine what the context of the app launch is
        if (NavigationContext.QueryString.ContainsKey("ProductName"))
        {
            _book = NavigationContext.QueryString["ProductName"];
            lblPageTitle.Text = "Book Details";
        }
        else
        {
            _book = null;
        }

        // In a "real" application we’d want to use binding and converters
        if (!string.IsNullOrWhiteSpace(_book))
        {
            lblBookTitle.Text = _book;
            lblNoSearch.Visibility = Visibility.Collapsed;
            lblBookTitle.Visibility = Visibility.Visible;
        }
        else
        {
            lblNoSearch.Visibility = Visibility.Visible;
            lblBookTitle.Visibility = Visibility.Collapsed;
        }
    }

    private void HandleSearchBarnesAndNoble(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(_book))
        {
            BrowseTo("http://www.barnesandnoble.com/ebooks/index.asp&quot;);
        }
        else
        {
            BrowseTo("http://productsearch.barnesandnoble.com/search/results.aspx?store=BOOK&keyword="&quot; + _book.Replace(" ", "+") + """);
        }
    }

    private void HandleSearchAmazonBooks(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(_book))
        {
            BrowseTo("http://www.amazon.com/gp/aw/sb.html/sn=Books&quot;);
        }
        else
        {
            BrowseTo("http://www.amazon.com/gp/aw/s/?k=&quot; + _book.Replace(" ", "+"));
        }
    }

    private static void BrowseTo(string address)
    {
        var webTask = new Microsoft.Phone.Tasks.WebBrowserTask { Uri = new Uri(address) };
        webTask.Show();
    }
}
 

Now when we launch our app through App Connect we see the following:

clip_image012

Supporting App Instant Answers

Another related feature introduced in Windows Phone Mango is App Instant Answers. This is an automatic feature of Bing search where apps Bing decides are relevant to a specific search are featured at the top of the search results. You don’t have to do anything in order to support launching from Instant Answers but you can take advantage of information passed in through this functionality if you choose. This information is exposed through a query string parameter called “bing_query” and is accessed similarly to the ProductName and Category query string parameters.

Modifying our sample app to take advantage of Instant Answers is extremely easy as illustrated by the modified top half of the HandleLoaded method:

// Determine what the context of the app launch is
if (NavigationContext.QueryString.ContainsKey("ProductName"))
{
    _book = NavigationContext.QueryString["ProductName"];
    lblPageTitle.Text = "Book Details";
}
else if (NavigationContext.QueryString.ContainsKey("bing_query"))
{
    _book = NavigationContext.QueryString["bing_query"];
    lblPageTitle.Text = "Related Search";
}
 

This modification allows the application to grab either the book title out of the Quick Card’s product name if one is present or from the Bing query that generated the Instant Answers result. The image below illustrates entering the app through an Instant Answers result for the search string “Sphere by Michael Crichton”

clip_image014

Testing App Connect

You might be wondering how to test Instant Answers or attach with a debugger when working with Search Extensions. This is a valid point since there isn’t currently a good way of influencing Bing search results using the emulator and when working with search extensions the Category attribute does not register the same as it would on the device. It also can become time consuming to navigate to Bing, execute a specific search and then launch the app using App Connect. Thankfully, there’s an easy way to simulate launching your app either through search extensions or through instant answers.

Since we can predict the query string parameters that Quick Cards will generate when entering our app, it is possible to hard code these values into the application’s entry point for testing purposes. Windows Phone apps store the default page’s address inside of the WMAppManifest.xml file in the properties node of the project. Open up this file and find the DefaultTask element inside the Tasks collection. It should look something like this:

<DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>

This element tells the application where to navigate when the application starts and can be modified to point to whatever file you desire. It can also be modified to simulate entering the app via search extensions or instant answers by specifying query string parameters. For example, the following entry was used to test Instant Answers in the section above:

<DefaultTask Name ="_default" NavigationPage="MainPage.xaml?bing_query=Sphere by Michael Crichton"/>

The modifications for simulating a search extension entry point for a similar product are very similar. Note that since we’re specifying multiple query string parameters that using &amp; to escape the ampersand is important as seen in the following snippet:

<DefaultTask Name ="_default" NavigationPage="MainPage.xaml?Category=Bing_Products_Books_and_Magazines&amp;ProductName=Sphere"/>

Of course, once you are done testing and ready to deploy the application, make sure you remove any hardcoded query string parameters from the default task so the app will function as intended.

You may occasionally run into deployment errors when making modifications to the WMAppManifest.xml file and attempting to launch the app in the emulator. If the deployment fails with the message: “Installation of the application failed. Run time error has occurred. Fix the Capabilities in WMAppManifest.xml file.” and your capabilities section looks fine, just rebuild the app and try again.

Summary

This wraps up coverage of App Connect and Instant Answers, two simple, flexible and easy to use ways to allow your app to integrate with extensibility points in the improved Bing search engine for Windows Phone Mango.

To download a complete working Windows Phone application that uses the code that was demonstrated in this article, click the Download Code button below:

download

Tomorrow, Samidip Basu is back to discuss the Execution Model of Windows Phone, including Fast App Switching, and how Tombstoning (which was covered in Day #14 of the 31 Days of Windows Phone) has changed slightly to accommodate the new 7.5 operating system.  See you then!

toolsbutton

Tags

9 responses to “31 Days of Mango | Day #22: App Connect”

  1. […] 31 Days of Mango | Day #22: App Connect – Jeff Blankenburg’s series of posts on Windows Phone Mango continue with another guest authored post, this time from Matt Eland. In this post Matt explores the App Connect functionality which allows you to combine your applications with others via search, instant answers and Quick Cards. […]

  2. […] 31 Days of Mango | Day #22: App Connect […]

  3. […] No trackbacks yet. « 31 Days of Mango | Day #22: App Connect […]

  4. […] Der Originalartikel befindet sich hier: Day #22: App Connect. […]

  5. […] Esta es una traducción de Dy 22: App Connect, puedes encontrarlo aquí en su versión original en i… […]

  6. […] Read original post by Matt Eland at BlankenBlog […]

  7. WPDev Sin: Envy « Windows Phone Love & .NET Ramblings Avatar

    […] App Connect: Did you know your app could be featured in the user’s Bing searches for tight integration? This, is called Search Extensibility or App Connect and in my opinion, a great way to showcase your app & keep bringing your users back into the app. More info & code samples here & here. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: