Auto-launching apps using file and URI associations for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

You can use file and URI associations in Windows Phone 8 to automatically launch your app when another app launches a specific file type or URI scheme. When launched, a deep link URI is used to send the file (a reference to the file) or URI to your app. You can also use the association launching API to launch another app in the same way. This topic describes file and URI associations, and how you can use them in your app.

Tip

Like Windows 8, Windows Phone 8 uses LaunchFileAsync to launch a file and LaunchUriAsync to launch a URI. However, the way Windows Phone XAML apps receive a file or URI is different. Also, Windows Phone does not have a “default” Store app. If there are multiple Store apps installed that can handle a particular file or URI association, the user chooses the receiving app from a menu.

This topic contains the following sections.

File associations

File associations allow your app to automatically launch when the user wants to open a particular file. That file could come from a variety of sources including, but not limited to:

  • an email attachment

  • a website via Internet Explorer

  • a Near Field Communications (NFC) tag

  • another app from the Store

File associations are also used to determine which file types apps can read from an SD card using the external storage APIs. For more info about these APIs, see Data for Windows Phone 8.

Registering for a file association

To handle a particular file type, register for a file association in the app manifest file. Your app can specify any file association that it is able to handle. However, any file associations that are reserved by built-in apps will be ignored. For more information, see Reserved file and URI associations for Windows Phone 8.

Note

Sometimes Internet Explorer overrides file associations: it launches the built-in media player to handle all music and video file types. Specifically, any file that has an audio/ or video/ content type. For example, your app can handle a (non-reserved) music and video file when it is launched from an email attachment. But if the same file is launched from Internet Explorer, the built-in media player will handle the file.

To provide an “integrated” look to custom file types appearing in built-in apps, you have the option of supplying logos (image files) to appear beside the files. For example, if a file (of your custom type) were attached to an email message, a small logo would appear beside the attachment after it was downloaded.

File type logos appear over a white background; be sure to review how your logo appears on the phone when you test your app. Also note that you won’t see your logo if more than one app has registered for the same file type. In that case, a generic logo is used. The following table lists the three image sizes that you can provide for each file association.

Logo Size

Use

Dimensions

Small

Email attachments

33x33 pixels

Medium

Office hub list view

69x69 pixels

Large

Browser download

176x176 pixels

Tip

As a best practice, we recommend that you store logos in the Assets folder of your app package.

To register for a file association, you must edit WMAppManifest.xml using the XML (Text) Editor. In Solution Explorer, right-click the WMAppManifest.xml file, and then click Open With. In the Open With window, select XML(Text) Editor, and then click OK.

In the Extensions element of the app manifest file, a file association is specified with the FileTypeAssociation element. Note that the Extensions element must immediately follow the Tokens element. The following example shows a file association for a fictitious file type called a “Windows Phone SDK test file type” that can handle two different file extensions: “.sdkTest1” and “.sdkTest2”.

<Extensions>
   <FileTypeAssociation Name="Windows Phone SDK test file type" TaskID="_default" NavUriFragment="fileToken=%s">
       <Logos>
           <Logo Size="small" IsRelative="true">Assets/sdk-small-33x33.png</Logo>
           <Logo Size="medium" IsRelative="true">Assets/sdk-medium-69x69.png</Logo>
           <Logo Size="large" IsRelative="true">Assets/sdk-large-176x176.png</Logo>
       </Logos>
       <SupportedFileTypes>
         <FileType ContentType="application/sdk">.sdkTest1</FileType>
         <FileType ContentType="application/sdk">.sdkTest2</FileType>

       </SupportedFileTypes>
   </FileTypeAssociation>
</Extensions>

Each of these elements is described in the following table.

Element

Parent element

Description

Extensions

App

Must follow the Tokens element.

FileTypeAssociation

Extensions

Describes a file association. You can register a maximum of 20 file associations, but each file association can only be listed once. The Name attribute is required, but you choose your own friendly name. Specify the TaskID and NavUriFragment elements as shown.

Logos

FileTypeAssociation

Lists all logos for a file association. This is optional when no logos are specified.

Logo

Logos

Optional. Lists an image file to appear beside a file. You must provide all sizes (Small, Medium, Large) if you provide any. The IsRelative attribute must be present and equal to true.

SupportedFileTypes

FileTypeAssociation

Lists all file extensions that are associated with the file type.

FileType

SupportedFileTypes

Lists the file extension that is associated with the file type, including the period (‘.’). You can associate a maximum of 20 file extensions with each file association, but each extension can only be used once. If your app reads files from the SD card, you must also specify the ContentType attribute to describe the type of file.

Listening for a file launch

When your app is launched to handle a particular file type, a deep link URI is used to take the user to your app. Within the URI, the FileTypeAssociation string designates that the source of the URI is a file association and the fileToken parameter contains the file token. For example, the following code shows a deep link URI from a file association.

/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19

Upon launch, map the incoming deep link URI to an app page that can handle the file. If you have multiple pages to handle multiple file types, use a custom URI mapper and the GetSharedFileName method to check the file type before mapping the URI. For example, the following code shows a URI mapper that parses the deep link URI and maps a different page depending on the type of file. If the launch is not from a file association, it sends the full URI string back to the App object in an unaltered state.

using System;
using System.IO;
using System.Windows.Navigation;
using Windows.Phone.Storage.SharedAccess;

namespace sdkAutoLaunch
{
    class AssociationUriMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = uri.ToString();

            // File association launch
            if (tempUri.Contains("/FileTypeAssociation"))
            {
                // Get the file ID (after "fileToken=").
                int fileIDIndex = tempUri.IndexOf("fileToken=") + 10;
                string fileID = tempUri.Substring(fileIDIndex);

                // Get the file name.
                string incomingFileName =
                    SharedStorageAccessManager.GetSharedFileName(fileID);

                // Get the file extension.
                string incomingFileType = Path.GetExtension(incomingFileName);

                // Map the .sdkTest1 and .sdkTest2 files to different pages.
                switch (incomingFileType)
                {
                    case ".sdkTest1":
                        return new Uri("/sdkTest1Page.xaml?fileToken=" + fileID, UriKind.Relative);
                    case ".sdkTest2":
                        return new Uri("/sdkTest2Page.xaml?fileToken=" + fileID, UriKind.Relative);
                    default:
                        return new Uri("/MainPage.xaml", UriKind.Relative);
                }
            }
            // Otherwise perform normal launch.
            return uri;
        }
    }
}

To use a URI mapper class like this in your app, assign it to the frame of the app in the App.xaml.cs file. In the InitializePhoneApplication method, just after RootFrame.Navigated is assigned, set the RootFrame.UriMapper property equal to your URI mapper class. In the following example, the AssociationUriMapper class is assigned to the frame’s UriMapper property.

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;

    // Assign the URI-mapper class to the application frame.
    RootFrame.UriMapper = new AssociationUriMapper();

    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Ensure we don't initialize again
    phoneApplicationInitialized = true;
}

When the app is launched, it assigns the URI mapper during initialization. Before launching any pages, the app calls the MapUri method of the URI mapper to determine which page to launch. The URI that the URI mapper returns is the page that the app launches.

When the page is launched, the page can access all of the parameters in the URI (that launched the page) using the QueryString property of the page’s NavigationContext object. For example, the following code puts all of the URI parameters and values into an IDictionary object.

// Get a dictionary of URI parameters and values.
IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;

Retrieving a file

After you have the file token from the deep link URI, access the file by using the SharedStorageAccessManager static class from the Windows.Phone.Storage.SharedAccess namespace. SharedStorageAccessManager provides the following methods.

Method

Return Type

Description

GetSharedFileName

System.String

Returns the name of the file (including the file extension).

CopySharedFileAsync

Windows.Storage.StorageFile

Copies the file to the specified location and returns the copy.

Launching a file

As mentioned earlier, your app also can launch a file, so another app can open it. To do this, use the LaunchFileAsync method from the Launcher object of the Windows.System namespace. For example, the following code launches a fictitious Contoso bug query file from local storage.

private async void LaunchFileButton_Click(object sender, RoutedEventArgs rea)
{

    // Access isolated storage.
    StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;

    // Access the bug query file.
    StorageFile bqfile = await local.GetFileAsync("file1.bqy");

    // Launch the bug query file.
    Windows.System.Launcher.LaunchFileAsync(bqfile);

}

URI associations

A URI association allows your app to automatically launch when another app launches a special URI. What makes that URI special is that it begins with a URI scheme name that your app has registered for. The URI scheme name is the portion of the URI that comes just before the colon (‘:’). The URI scheme includes the URI scheme name and all of the URI that follows the colon. For example, in the following URI scheme, contoso is the URI scheme name.

contoso:ShowProducts?CategoryID=aea6ae1f-9894-404e-8bca-ec47ec5b9c6c

After the colon, the rest of the URI is open to however you want to use the URI association. When your app is launched, it has the opportunity to inspect the URI and behave differently based on what is in the URI. In this example, the receiving app has been designed to show all products within a particular category.

Tip

If you are interested only in launching your own apps, consider using APIs from the Windows.Phone.Management.Deployment namespace. You can use this API to check for other apps that you’ve published, and then launch them if they’re installed. For more info, see Launching, resuming, and multitasking for Windows Phone 8.

Registering for a URI association

To handle a URI association, specify the corresponding URI scheme name in the app manifest file, WMAppManifest.xml. Your URI scheme name can be any combination of letters and numbers; however, any URI scheme names that are reserved by built-in apps will be ignored. For more information, see Reserved file and URI associations for Windows Phone 8.

To register for a URI association, you must edit WMAppManifest.xml using the XML (Text) Editor. In Solution Explorer, right-click the WMAppManifest.xml file, and then click Open With. In the Open With window, select XML(Text) Editor, and then click OK.

In the Extensions element of the app manifest file, a URI association is specified with a Protocol element. Note that the Extensions element must immediately follow the Tokens element. You can register a maximum of 10 URI associations in each app. The following example shows a URI association for a fictitious app that handles the contoso URI scheme name.

<Extensions>
  <Protocol Name="contoso" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>

The Protocol element is made up of following attributes.

Attribute

Description

Name

The prefix in your custom URI scheme. A string between 2 and 39 characters in length that contains numbers, lowercased letters, periods ('.'), or hyphens ('-'). It does not include the colon (':') or anything else that will follow it in the URI.

NavUriFragment

Must always equal encodedLaunchUri=%s

TaskID

Must always equal _default

Listening for a URI

When your app is automatically launched to handle a URI association, a deep link URI is used to take the user to your app. Within the URI, the Protocol string designates that the source of the URI is a URI association. The URI parameter named encodedLaunchuri equals a URI-encoded version of the whole URI scheme sent from the originating app. For example, the following code shows the launch URI that this fictitious app sees when it is launched as a result of a contoso URI association.

/Protocol?encodedLaunchUri=contoso%3AShowProducts%3FCategoryID%3Daea6ae1f-9894-404e-8bca-ec47ec5b9c6c
Important Note:

All reserved characters in the URI scheme from the launching app are automatically percent-encoded. For example, one app launching the URI “contoso:NewProducts” will result in another app receiving the deep link URI “/Protocol?encodedLaunchUri=contoso%3ANewProducts”.

When it launches, map the incoming deep link URI to an app page that can handle the URI association. The following example shows a custom URI mapper that maps a Contoso “show products” request with the ShowProducts.xaml page. When the contoso URI scheme name is not used, the full URI is sent to the MainPage.xaml page.

using System;
using System.Windows.Navigation;

namespace sdkAutoLaunch
{
    class AssociationUriMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());

            // URI association launch for contoso.
            if (tempUri.Contains("contoso:ShowProducts?CategoryID="))
            {
                // Get the category ID (after "CategoryID=").
                int categoryIdIndex = tempUri.IndexOf("CategoryID=") + 11;
                string categoryId = tempUri.Substring(categoryIdIndex);

                // Map the show products request to ShowProducts.xaml
                return new Uri("/ShowProducts.xaml?CategoryID=" + categoryId, UriKind.Relative);
            }

            // Otherwise perform normal launch.
            return uri;
            }
        }
}

To use a URI mapper class like this one in your app, assign it to the frame of the app in the App.xaml.cs file. In the InitializePhoneApplication method, just after RootFrame.Navigated is assigned, assign the RootFrame.UriMapper property to your URI mapper class. In the following example, the AssociationUriMapper class is assigned to the frame’s UriMapper property.

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;

    // Assign the URI-mapper class to the application frame.
    RootFrame.UriMapper = new AssociationUriMapper();

    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Ensure we don't initialize again
    phoneApplicationInitialized = true;
}

When the app is launched, it assigns the URI mapper during initialization. Before launching any pages, the app calls the MapUri method of the URI mapper to determine which page to launch. The URI that the URI mapper returns is the page that the app launches.

When the page is launched, the page can access all of the parameters in the URI (that launched the page) using the QueryString property of the page’s NavigationContext object. For example, the following code puts all of the URI parameters and values in an IDictionary object.

// Get a dictionary of URI parameters and values.
IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;

Launching a URI

By using the association launching API, your app can automatically launch another app by launching a custom URI. To do this, use the Launcher..::.LaunchUriAsync(Uri) method from the Launcher object of the Windows.System namespace. For example, the following code launches a fictitious Contoso app to display new products.

private async void LaunchContosoNewProductsButton_Click(object sender, RoutedEventArgs rea)
{
    // Launch URI.
    Windows.System.Launcher.LaunchUriAsync(new System.Uri("contoso:NewProducts"));
}

When your URI is passed to the receiving app with a URI association, all reserved characters in the launched URI are automatically percent-encoded. For example, one app launching the URI “contoso:NewProducts” will result in another app receiving the deep link URI “/Protocol?encodedLaunchUri=contoso%3ANewProducts”.

Launching a URI using Proximity

Windows Phone 8 supports Proximity communication using Near Field Communication (NFC). By using the Proximity API, your app can launch another app on another phone. If the other phone is a Windows Phone 8 device and supports NFC, the other phone will handle the URI association in the same way as it would a locally launched URI. For more info about using Proximity in your app, see Proximity for Windows Phone 8.

ProximityDevice device = ProximityDevice.GetDefault();

// Make sure NFC is supported
if (device != null)
{
    long Id = device.PublishUriMessage(new System.Uri("contoso:NewProducts"));
    Debug.WriteLine("Published Message. ID is {0}", Id);

    // Store the unique message Id so that it 
    // can be used to stop publishing this message
}

How association works for the user

When the user launches a file or URI from an app, what happens next depends on which apps are installed on the phone. If no apps on the phone can handle that particular file or URI association, the user will be given the option to get one that does.

When there is only one app on the phone registered for a particular file or URI association, that app will be automatically launched when the user wants to open it. If a user has more than one app on their phone registered for a file or URI association, each time the user opens the file, they will be as asked which app they want to use.

Tip

Don’t register for a file or URI association unless you can perform a useful action with it. If your app causes the app menu to be shown frequently, the user may choose to uninstall it altogether to avoid having to always make a choice.

See Also

Other Resources

URI schemes for launching built-in apps for Windows Phone 8

Reserved file and URI associations for Windows Phone 8

Launching, resuming, and multitasking for Windows Phone 8

Launchers and Choosers for Windows Phone 8

Launchers and choosers for Direct3D apps for Windows Phone 8