31 Days of Windows 8 | Day #18: File Associations & App Contracts

This article is Day #18 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, we are going to look at a couple of cool features in Windows 8: File Associations and App Contracts.  With file associations, we’ll look at both sides of this Windows 8 feature:

  • Registering our app with Windows 8 as an app that opens files of a certain type, like .png, or a custom extension, .31days.
  • Empowering our app to suggest a list of compatible applications when our user tries to open a file that our app doesn’t support, like an .xls file.

Finally, we’ll also discuss some of the other ways our application can register with the user’s system, including things like AutoPlay.

Registering to Open Certain File Types

There’s going to be times that we want to have our user open files of a certain type in our application.  Maybe we are creating an image editor, so no matter what type of image format the user’s files are in, if they’re a common image type, we should be able to open it.  Perhaps we’re building an XML editor that consumes .xml files.  In either case, we want to register our app with the user’s system, so that when they get a prompt like this:

18-XAML-OpenDialog

We want to make sure that our app is in this list when a user opens files appropriate for our application.  To do this, it’s as simple as making some simple changes to our package.appxmanifest file.  Open the file, and choose the declarations tab.  From the “Available Declarations” selection list, choose “File Type Associations,” and click Add.

You will see that it fills the screen with a new form for specifying the file associations you would like to register your app with.  By default, it has a few red Xs that you will need to address.

18-XAML-DeclarationsBroken

For this sample, I am going to pick two different file types.  The first will be a custom extension that files created by my app will use: “31days".  The other will be to register with the “png” extension, so we can try to open images with this application as well.

18-XAML-DeclarationsFixed

The first value, Name, is just a name for the set of extensions you are listing here.  The reason that we can have different sets of extensions is because you might want your app to act differently depending on the file type.  At the bottom of the form, you can specify the entry point for your application for this set of files.  If it’s an XML file, you might want to take them directly to your text editor page.  If it’s an image, perhaps you’d rather take them to an image editing page, or just attach it to an email.  That’s up to you.

Once you’ve done that, you’re basically done.  Run the application once, to install it on your system, and then try to do an “Open With” for the specific file types you used.  The easiest way to test this is to jump to your Desktop, and create a new Text File.  I named mine Blankenburg.31days as the file name.  First, you’ll get the standard warning for renaming files:

18-XAML-FileRenameWarning

Then, you’ll get an icon that looks like all of the default icons that come with a default project.  The only problem is, I don’t have an image that looks like that in my project anymore, so I’m not sure where this one comes from.  Here’s my file sitting on the desktop:

18-XAML-FileNoLogo

That’s not going to work.  We want our logo or icon to appear when we are the default application for a file type.  Just as Excel files have an Excel icon, so too should .31days files have a 31 Days icon.  To do this, jump back into your package.appxmanifest file, and specify a logo in the section where you specified name, like this:

18-XAML-DeclarationsLogo

You can use any icon you’d like, but they do have a square aspect ratio, so I chose my Logo.png file which has the same ratio.  You’ll end up with files that look like this (make sure to run your app again to update your system):

18-XAML-FileLogo

In addition, when we right-click on this file and choose “Open With…” we get this menu now:

 18-XAML-31DaysExtensionDialog

You can see that we’ve found yet another location where our SmallLogo.png file is being used by default, with no place to change it.  Finally, since we also registered our app for “.png” files, let’s take a look at what opening one of those looks like:

18-XAML-PNGAssociation

So, for step one of our article, we’ve demonstrated how to set file associations for your application in Windows 8.  In the next section, we’re going to look at how we prompt the user to open a file from our app to another app.

Opening a File In Another App

Sometimes, your application just can’t open every single file type.  For example, Microsoft Outlook is really good at accepting images, text, and files, but if you’ve ever tried to open an Excel file attached to an email, you’ve probably noticed (and come to expect) that the file gets opened in Excel, not Outlook.  We want to provide that same functionality to our users.  To do this, we are going to explore the Windows.System.Launcher class.

In our first simple example, we’re just going to launch our file (the Excel file from Day #17) without any options or settings.  The system will use the default app to launch our file, without any choice or warning.

Uri uri = new Uri("ms-appx:///Assets/PeriodicTable.xls");
StorageFile sf = await StorageFile.GetFileFromApplicationUriAsync(uri);
await Launcher.LaunchFileAsync(sf);
 

As you can see in this first example, it’s pretty simple.  We call Launcher.LaunchFileAsync(), and pass it a StorageFile object.  Sometimes, however, you might want to warn your user that you are going to be launching another piece of software, so that they get to decide if that’s really what they want to do.  In this case, we can create a LauncherOptions object, and provde that as part of our LaunchFileAsync() call.  Like this:

Uri uri = new Uri("ms-appx:///Assets/PeriodicTable.xls");
StorageFile sf = await StorageFile.GetFileFromApplicationUriAsync(uri);
 
LauncherOptions options = new LauncherOptions();
options.TreatAsUntrusted = true;
 
bool action = await Launcher.LaunchFileAsync(sf, options);
 

When we do this, an alert pops up on the screen letting the user know that another application is being opened.

18-XAML-SwitchingAppsAlert

Finally, there may be a time where you want your user to be able to select the app that they will open a file with.  In this case, we want to bring up the same box that appears when a user selected “Open With…” in the previous section.  To do this, we just set another option: DisplayApplicationPicker.  If you want to modify the position of this box, there’s a little more work, but it’s very similar to what we did on Day #16 with context menus: we need to determine where on the screen to show the box.

If you don’t specify a location, however, it will launch the dialog box centered on the user’s screen.  Personally, I prefer how this looks to having it closer to the control the user clicked, but I understand what the Windows team is trying to do.  Here’s screenshots of the difference (click to enlarge):

Open With Dialog Centered Open With Dialog Positioned
18-XAML-OpenWithCentered 18-XAML-OpenWithPositioned

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }  And here’s the code to make it happen.  (If you don’t want your box to be positioned, which is actually my recommendation, just chop out the pieces that are related to positioning.)

private async void OpenExcelButtonWithOpenWithMenu_Click(object sender, RoutedEventArgs e)
{
    Uri uri = new Uri("ms-appx:///Assets/PeriodicTable.xls");
    StorageFile sf = await StorageFile.GetFileFromApplicationUriAsync(uri);
 
    LauncherOptions options = new LauncherOptions();
    options.DisplayApplicationPicker = true;
    options.UI.InvocationPoint = GetPosition(sender as FrameworkElement);
    options.UI.PreferredPlacement = Placement.Below;
 
    bool action = await Launcher.LaunchFileAsync(sf, options);
}
 
private Point GetPosition(FrameworkElement sender)
{
    GeneralTransform transform = sender.TransformToVisual(null);
    Point location = transform.TransformPoint(new Point());
    location.Y = location.Y + sender.ActualHeight;
 
    return location;
}
 

So there you have it.  Three different ways to launch a file in a separate application from your own.  In the final section of this article, we’re going to look at App Contracts, and how we can make our apps available in other lists for our users.

Using App Contracts for Good

When reading this article, some developers will think that it’s a good idea to register their app for every possible file extension, because it will keep their app and logo in front of their users as often as possible.

PLEASE DON’T DO THAT.

That rule applies to App Contracts as well.  Don’t abuse them, especially if you aren’t actually providing the functionality required.  This will be reviewed when you submit your application to the store, so it will be discovered.

Account Picture Provider

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

You can declare this functionality if you can provide the ability for the user to create a new Account Picture in Windows 8.  You get to the menu on the Start Screen, like this:

18-XAML-AccountPicture

And when your app is registered, the options will look like this, with your app listed:

18-XAML-PersonalizeMenu
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

To do this, just add the Account Picture Provider to your declarations tab in your package.appxmanifest file, like this:

18-XAML-AccountPictureProvider

By default, it will just launch your app, but you can also provide custom entry points, so that the user ends up on the right section of your app automatically.

AutoPlay and Protocols

There are three other App Contracts we can subscribe to, and each of them only really requires another entry in the Declarations.

“AutoPlay Content” recognizes when new media is inserted into the device, like a USB drive or DVD.  If the content type you register for is present, your app will appear in the AutoPlay list that is displayed.  There is an excellent article on MSDN about AutoPlay, and the different values you can use.

“AutoPlay Device” is basically the same idea, but you’re registering for specific types of devices, like cameras, printers, or USB drives.  The same article above applies to this as well.

“Protocol” is a little different.  This allows us to register for URI schemes, like “mailto:” or even use our own custom URI schemes like “31days:.”  It’s another way to register our application with the system to be used at the appropriate times.  Microsoft has an excellent article about protocols as well.

Summary

Today, we looked at some of the extensible points we can access to make our app more prominent and useful to our users.  If they expect to be able to open images with our application, then we should show up in their list of apps when they try to open an image.

If you would like to see the full working solution for the code covered in this article, click the download icon below:

downloadXAML 

Tomorrow, we’re going to look at another powerful mechanism in Windows 8: the File Picker.  This empowers our user to grab files from their hard drive, and provide them to our applications.  See you then!

downloadTheTools

One thought on “31 Days of Windows 8 | Day #18: File Associations & App Contracts

  1. Pingback: Windows Store Developer Links – 2012-12-10 | Dan Rigby

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s