Introduction
Windows Phone 8 allows an application to register file and URI associations, which can be used to auto-launch an application. On Windows Phone 8, this enables scenarios such as prompting the user to select one of the available registered applications, which can open a file attachment of a specific type in your inbox. In certain cases, it may be desirable to navigate directly to a specific page inside a Windows Phone 8 application instead of the default home page. URI associations will help for that use case.
File Association Basics
As mentioned above, file association is typically desired when an application, which can work with a certain file type, wants to be available as one of the launchable applications. This will be useful in cases like opening an email attachment or opening the Windows Phone Store application.
File associations for a Windows Phone application are registered in the application manifest file. Please note that certain file associations are reserved by the operating system for built-in applications (like Internet Explorer). In those cases, the file associations will be ignored.
The following file types are reserved for built-in Windows Phone 8 application:
- .aac
- .aetx
- .asf
- .bmp
- .cer
- .dotm
- .dotx
- .gif
- .hdp
- .htm
- .html
- .ico
- .icon
- .jpeg
- .jxr
- .m4a
- .m4r
- .m4v
- .mov
- .mp3
- .mp4
- .one
- .onetoc2
- .p7b
- .pem
- .png
- .pptm
- .qcp
- .rtf
- .tif
- .tiff
- .txt
- .url
- .vcf
- .wav
- .wdp
- .wmv
- .xap
- .xht
- .xhtml
- .xltm
- .xltx
- .xml
- .xsl
- .zip
The following file types are reserved for the Windows Phone 8 operating system:
- .ade
- .adp
- .app
- .application
- .appref-ms
- asp
- .bas
- .bat
- .cab
- .chm
- .cmd
- .cnt
- .com
- .cpf
- .cpl
- .crd
- .crds
- .crt
- .csh
- .der
- .dll
- .exe
- .fxp
- .gadget
- .grp
- .hlp
- .hme
- .hpj
- .hta
- .inf
- .ins
- .isp
- .its
- .jar
- .js
- .jse
- .ksh
- .lnk
- .mad
- .maf
- .mag
- .mam
- .maq
- .mar
- .mas
- .mat
- .mau
- .mav
- .maw
- .mcf
- .mda
- .mdb
- .mde
- .mdt
- .mdw
- .mdz
- .msc
- .msh
- .msh1
- .msh1xml
- .msh2
- .msh2xml
- .mshxml
- .msi
- .msp
- .mst
- .msu
- .ops
- .pcd
- .pif
- .pl
- .plg
- .plsc
- .prf
- .prg
- .printexport
- .provxml
- .ps1
- .ps1xml
- .ps2
- .ps2xml
- .psc1
- .psc2
- psm1
- pst
- pvw
- .py
- .pyc
- .pyo
- .rb
- .rbw
- .rdp
- .reg
- .rgu
- .scf
- .scr
- .shb
- .shs
- .theme
- .tmp
- .tsk
- .url
- .vb
- .vbe
- .vbp
- .vbs
- .vhd
- .vhdx
- .vsmacros
- .vsw
- .webpnp
- ..ws .
- .wsc
- .wsf
- .wsh
- .xaml
- .xdp
- xip
- xnk
To provide a great user experience, you can provide logo images for your file extension. You can provide three different logo image files (one for small size (33 x 33 pixels), one for medium size (69 x 69 pixels) and one for large size(176 x 176 pixels)).
If logo images are not specified, default logo images are displayed.
Each Windows Phone 8 application can register up to 20 file extensions. The extension registration is done in the WMAppManifest.xml file.
A deep URI is used to take the user to the application when the application is launched to handle a specific file type. If the URI contains the string “FileTypeAssociation”, it means that the source of launch was a file association.
Since the deep URI only contains a GUID representing the file to be opened, we need to use the SharedStorageAccessManager class’ GetSharedFileName api to get the name of the file.
If your application can handle multiple file types, you can have multiple landing pages based on the file type and decide the page to open depending on the file extension.
URI Association Basics
With URI association, your application can be automatically launched from another application when it invokes a specific URI. A classic example is launching of the Windows Phone 8 store when we click the “Get” link on the Windows Phone store website. The URI begins with the URI scheme, which the application has registered for.
Similar to file extensions, URI associations are registered in WMAppManifest.xml file under “Protocol” node.
A deep link URI is used to navigate the user to the application when the application is launched as a result of URI association.
A typical URI looks like:
/Protocol?encodedLaunchUri=”contoso%3AShowProducts%3FCategoryID%3Daea6ae1f-9894-404e-8bca-ec47ec5b9c6c”
Where encodedLaunchUri value (highlighted) reflects the version of the URI scheme sent from the originating application. The invoked application should listen for how the application was invoked and redirect to a dedicated page, which can handle the request.
If a URI scheme is reserved for built-in apps or Windows Phone operating systems, any attempts to register the URI scheme will be ignored.
The following URI schemes are reserved for built-in apps:
- bing
- callto
- dtmf
- http
- https
- mailto
- maps
- ms-excel
- ms-powerpoint
- ms-settings-airplanemode
- ms-settings-bluetooth
- ms-settings-cellular
- ms-settings-emailandaccounts
- ms-settings-location
- ms-settings-lock
- ms-settings-wifi
- ms-word office
- onenote
- tel
- wallet
- xbls
- zune
The following URI schemes are reserved for the Windows Phone operating system:
- Explorer.AssocActionId.BurnSelection
- Explorer.AssocActionId.CloseSession
- Explorer.AssocActionId.EraseDisc
- Explorer.AssocActionId.ZipSelection
- Explorer.AssocProtocol.search-ms
- Explorer.BurnSelection
- Explorer.CloseSession
- Explorer.EraseDisc
- Explorer.ZipSelection
- File
- Iehistory
- Ierss
- Javascript
- Jscript
- LDAP
- Res
- rlogin
- StickyNotes
- telnet
- tn3270
- Vbscript
- windowsmediacenterapp
- windowsmediacenterssl
- windowsmediacenterweb
- WMP11.AssocProtocol.MMS
Hands-On
Create a new Visual Studio 2012 project titled WindowsPhoneFileAndURIAssociationDemo.
New Visual Studio 2012 Project
When prompted, select Windows Phone OS 8.0 as the target Windows Phone OS version.
Target Windows Phone OS Version
We will register our application to associate it with files with extension “foo”, and “bar”, and URI scheme “foobar”.
To register the associations, open WMAppManifest.xml from Solution explorer by right clicking and selecting View Code.
View Code
Next, we add the following entries in the application manifest file to register file extensions “foo” and “bar”, and URI scheme “foobar”.
<?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="{a405b9f4-de5d-47e7-8c37-707ae6bab153}" Title="WindowsPhoneFileandURIAssociationDemo" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="WindowsPhoneFileandURIAssociationDemo author" Description="Sample description" Publisher="WindowsPhoneFileandURIAssociationDemo" PublisherID="{32654afb-f1a9-4c7b-b491-618269aea4f7}"> <IconPath IsRelative="true" IsResource="false">AssetsApplicationIcon.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="WindowsPhoneFileandURIAssociationDemoToken" TaskName="_default"> <TemplateFlip> <SmallImageURI IsRelative="true" IsResource="false">AssetsTilesFlipCycleTileSmall.png</SmallImageURI> <Count>0</Count> <BackgroundImageURI IsRelative="true" IsResource="false">AssetsTilesFlipCycleTileMedium.png</BackgroundImageURI> <Title>WindowsPhoneFileandURIAssociationDemo</Title> <BackContent></BackContent> <BackBackgroundImageURI></BackBackgroundImageURI> <BackTitle></BackTitle> <DeviceLockImageURI></DeviceLockImageURI> <HasLarge></HasLarge> </TemplateFlip> </PrimaryToken> </Tokens> <Extensions> <FileTypeAssociation Name="Windows Phone File and URI Association demo" TaskID="_default" NavUriFragment="fileToken=%s"> <!--<Logos> <If you want to specify your own logo files, you can do it here> <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/foo">.foo</FileType> <FileType ContentType="application/bar">.bar</FileType> </SupportedFileTypes> </FileTypeAssociation> <Protocol Name="foobar" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" /> </Extensions> <ScreenResolutions> <ScreenResolution Name="ID_RESOLUTION_WVGA"/> <ScreenResolution Name="ID_RESOLUTION_WXGA"/> <ScreenResolution Name="ID_RESOLUTION_HD720P"/> </ScreenResolutions> </App> </Deployment>
Please note that I have commented out the block to specify custom logo files for your extension. That is left as an exercise to the reader. Please be sure to adhere to the image size and file format for your logo images.
Next, we will add three pages to your application – one each for each registered file extension and one for the URI schemes registered for the application. We will code our application to launch the appropriate page depending on what caused the application to be launched – file extension or URI schema invocation.
We will call these pages as FileExtensionFooLandingPage.xaml, FileExtensionBarLandingPage.xaml, and URISchemeFooBarLandingPage.xaml.
These pages should look like this:
Foo Landing Page
Bar Landing Page
FooBar Landing Page
Next, we will write a class, which will be responsible for mapping the URIs to invoke when the application is launched, depending on the context that caused the application to be launched.
We will call this the UriMapper class. The implementation will be as follows:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Navigation; using Windows.Phone.Storage.SharedAccess; namespace WindowsPhoneFileandURIAssociationDemo { class UriMapper : UriMapperBase { public override Uri MapUri(Uri uri) { string uriToLaunch = uri.ToString(); // File association launch if (uriToLaunch.Contains("/FileTypeAssociation")) { int fileIDIndex = uriToLaunch.IndexOf("fileToken=") + "fileToken=".Length; string fileID = uriToLaunch.Substring(fileIDIndex); // Get the file name. string incomingFileName = SharedStorageAccessManager.GetSharedFileName(fileID); // Get the file extension. string incomingFileType = Path.GetExtension(incomingFileName); // Map the file extension to different pages. switch (incomingFileType) { case ".foo": return new Uri("/FileExtensionFooLandingPage.xaml?fileToken=" + fileID, UriKind.Relative); case ".bar": return new Uri("/FileExtensionBarLandingPage.xaml?fileToken=" + fileID, UriKind.Relative); default: return new Uri("/MainPage.xaml", UriKind.Relative); } } else if (System.Net.HttpUtility.UrlDecode(uriToLaunch).Contains("foobar:ShowURIPage?UniqueID=")) {
string uniqueId = uriToLaunch.Substring(System.Net.HttpUtility.UrlDecode(uriToLaunch).IndexOf("UniqueID=") + "UniqueID=".Length); // Map the request to URIScheme Landing page URISchemeFooBarLandingPage.xaml return new Uri("/URISchemeFooBarLandingPage.xaml?UniqueID=" + uniqueId, UriKind.Relative); } // Otherwise perform normal launch. return uri; } } }
Next, we will assign the URI mapper to the frame of the app in the App.xaml.cs in the InitializePhoneApplication() method.
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 UriMapper(); // 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; }
Now, we are ready to start testing our application.
Testing the Application
You can now compile and execute your application. Open Internet Explorer on the emulator or the Windows Phone device and point it to http://sdrv.ms/15EbmcB, which contains two files – one with extension .foo and the other with extension .bar. When you attempt to open the files, our application will automatically open with the corresponding landing page depending on the file extension you selected.
Test
Bar Landing Page
When I open the word doc and click on the link, it opens The FooBar landing page.
Test URI Link
FooBar Landing Page
If you are having trouble following along, you can download the sample code listing from here.
Summary
In this article, we learned about two important concepts, file extension registration and URI association. 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 .