2015-04-02

In this tutorial, we’re going to explore various ways to integrate our application with the features offered by the Windows Phone platform. We’ll explore launches and choosers, learn how to interact with contacts and appointments, and see how to take advantage of Kid’s Corner, an innovative feature introduced to allow kids to safely use the phone.

Launchers and Choosers

When we discussed storage earlier in this series, we introduced the concept of isolated applications. In the same way that storage is isolated such that you can’t access the data stored by another application, the application itself is isolated from the operating system.

The biggest benefit of this approach is security. Even if a malicious application is able to pass the certification process, it won’t have the chance to do much damage because it doesn’t have direct access to the operating system. But sooner or later, you’ll need to interact with one of the many Windows Phone features, like sending a message, making a phone call, playing a song, etc.

For all these scenarios, the framework has introduced launchers and choosers, which are sets of APIs that demand a specific task from the operating system. Once the task is completed, control is returned to the application.

Launchers are “fire and forget” APIs. You demand the operation and don’t expect anything in return—for example, starting a phone call or playing a video.

Choosers are used to get data from a native application—for example, contacts from the People Hub—and import it into your app.

All the launchers and choosers are available in the Microsoft.Phone.Tasks namespace and share the same behavior:

Every launcher and chooser is represented by a specific class.

If needed, you set some properties that are used to define the launcher or chooser’s settings.

With a chooser, you’ll need to subscribe to the Completed event, which is triggered when the operation is completed.

The Show() method is called to execute the task.

Note: Launchers and choosers can’t be used to override the built-in Windows Phone security mechanism, so you won’t be able to execute operations without explicit permission from the user.

In the following sample, you can see a launcher that sends an email using the EmailComposeTask class:

The following sample demonstrates how to use a chooser. We’re going to save a new contact in the People Hub using the SaveContactTask class.

Every chooser returns a TaskResult property, with the status of the operation. It’s important to verify that the status is TaskResult.OK before moving on, because the user could have canceled the operation.

The following is a list of all the available launchers:

MapsDirectionTask is used to open the native Map application and calculate a path between two places.

MapsTask is used to open the native Map application centered on a specific location.

MapDownloaderTask is used to manage the offline maps support new to Windows Phone 8. With this task, you’ll be able to open the Settings page used to manage the downloaded maps.

MapUpdaterTask is used to redirect the user to the specific Settings page to check for offline maps updates.

ConnectionSettingsTask is used to quickly access the different Settings pages to manage the different available connections, like Wi-Fi, cellular, or Bluetooth.

EmailComposeTask is used to prepare an email and send it.

MarketplaceDetailTask is used to display the detail page of an application on the Windows Phone Store. If you don’t provide the application ID, it will the open the detail page of the current application.

MarketplaceHubTask is used to open the Store to a specific category.

MarketplaceReviewTask is used to open the page in the Windows Phone Store where the user can leave a review for the current application.

MarketplaceSearchTask is used to start a search for a specific keyword in the Store.

MediaPlayerLauncher is used to play audio or a video using the internal Windows Phone player. It can play both files embedded in the Visual Studio project and those saved in the local storage.

PhoneCallTask is used to start a phone call.

ShareLinkTask is used to share a link on a social network using the Windows Phone embedded social features.

ShareStatusTask is used to share custom status text on a social network.

ShareMediaTask is used to share one of the pictures from the Photos Hub on a social network.

SmsComposeTask is used to prepare a text message and send it.

WebBrowserTask is used to open a URI in Internet Explorer for Windows Phone.

SaveAppointmentTask is used to save an appointment in the native Calendar app.

The following is a list of available choosers:

AddressChooserTask is used to import a contact’s address.

CameraCaptureTask is used to take a picture with the integrated camera and import it into the application.

EmailAddressChooserTask is used to import a contact’s email address.

PhoneNumberChooserTask is used to import a contact’s phone number.

PhotoChooserTask is used to import a photo from the Photos Hub.

SaveContactTask is used to save a new contact in the People Hub. The chooser simply returns whether the operation completed successfully.

SaveEmailAddressTask is used to add a new email address to an existing or new contact. The chooser simply returns whether the operation completed successfully.

SavePhoneNumberTask is used to add a new phone number to an existing contact. The chooser simply returns whether the operation completed successfully.

SaveRingtoneTask is used to save a new ringtone (which can be part of the project or stored in the local storage). It returns whether the operation completed successfully.

Getting Contacts and Appointments

Launchers already provide a basic way of interacting with the People Hub, but they always require user interaction. They open the People Hub and the user must choose which contact to import.

However, in certain scenarios you need the ability to programmatically retrieve contacts and appointments for the data. Windows Phone 7.5 introduced some new APIs to satisfy this requirement. You just have to keep in mind that, to respect the Windows Phone security constraints, these APIs only work in read-only mode; you’ll be able to get data, but not save it (later in this article, we’ll see that Windows Phone 8 has introduced a way to override this limitation).

In the following table, you can see which data you can access based on where the contacts are saved.

Provider

Contact Name

Contact Picture

Other Information

Calendar Appointments

Device

Yes

Yes

Yes

Yes

Outlook.com

Yes

Yes

Yes

Yes

Exchange

Yes

Yes

Yes

Yes

SIM

Yes

Yes

Yes

No

Facebook

Yes

Yes

Yes

No

Other social networks

No

No

No

No

To know where the data is coming from, you can use the Accounts property, which is a collection of the accounts where the information is stored. In fact, you can have information for the same data split across different accounts.

Working With Contacts

Each contact is represented by the Contact class, which contains all the information about a contact, like DisplayName, Addresses, EmailAddresses, Birthdays, etc. (basically, all the information that you can edit when you create a new contact in the People Hub).

Note: To access the contacts, you need to enable the ID_CAP_CONTACTS option in the manifest file.

Interaction with contacts starts with the Contacts class which can be used to perform a search by using the SearchAsync() method. The method requires two parameters: the keyword and the filter to apply. There are two ways to start a search:

A generic search: The keyword is not required since you’ll simply get all the contacts that match the selected filter. This type of search can be achieved with two filter types: FilterKind.PinnedToStart which returns only the contacts that the user has pinned on the Start screen, and FilterKind.None which simply returns all the available contacts.

A search for a specific field: In this case, the search keyword will be applied based on the selected filter. The available filters are DisplayName, EmailAddress, and PhoneNumber.

The SearchAsync() method uses a callback approach; when the search is completed, an event called SearchCompleted is raised.

In the following sample, you can see a search that looks for all contacts whose name is John. The collection of returned contacts is presented to the user with a ListBox control.

Tip: If you want to start a search for another field that is not included in the available filters, you’ll need to get the list of all available contacts by using the

FilterKind.None

option and apply a filter using a LINQ query. The difference is that built-in filters are optimized for better performance, so make sure to use a LINQ approach only if you need to search for a field other than a name, email address, or phone number.

Working With Appointments

Getting data from the calendar works in a very similar way: each appointment is identified by the Appointment class, which has properties like Subject, Status, Location, StartTime, and EndTime.

To interact with the calendar, you’ll have to use the Appointments class that, like the Contacts class, uses a method called SearchAsync() to start a search and an event called SearchCompleted to return the results.

The only two required parameters to perform a search are the start date and the end date. You’ll get in return all the appointments within this time frame. Optionally, you can also set a maximum number of results to return or limit the search to a specific account.

In the following sample, we retrieve all the appointments that occur between the current date and the day before, and we display them using a ListBox control.

Tip: The only way to filter the results is by start date and end date. If you need to apply additional filters, you’ll have to perform LINQ queries on the results returned by the search operation.

A Private Contact Store for Applications

The biggest limitation of the contacts APIs we’ve seen so far is that we’re only able to read data, not write it. There are some situations in which having the ability to add contacts to the People Hub without asking the user’s permission is a requirement, such as a social network app that wants to add your friends to your contacts list, or a synchronization client that needs to store information from a third-party cloud service in your contact book.

Windows Phone 8 has introduced a new class called ContactStore that represents a private contact book for the application. From the user’s point of view, it behaves like a regular contacts source (like Outlook.com, Facebook, or Gmail). The user will be able to see the contacts in the People Hub, mixed with all the other regular contacts.

From a developer point of view, the store belongs to the application; you are free to read and write data, but every contact you create will be part of your private contact book, not the phone’s contact list. This means that if the app is uninstalled, all the contacts will be lost.



The ContactStore class belongs to the Windows.Phone.PersonalInformation namespace and it offers a method called CreateOrOpenAsync(). The method has to be called every time you need to interact with the private contacts book. If it doesn’t exist, it will be created; otherwise, it will simply be opened.

When you create a ContactStore you can set how the operating system should provide access to it:

The first parameter’s type is ContactStoreSystemAccessMode, and it’s used to choose whether the application will only be able to edit contacts that belong to the private store (ReadOnly), or the user will also be able to edit information using the People Hub (ReadWrite).

The second parameter’s type is ContactStoreApplicationAccessMode, and it’s used to choose whether other third-party applications will be able to access all the information about our contacts (ReadOnly) or only the most important ones, like name and picture (LimitedReadOnly).

The following sample shows the code required to create a new private store:

Tip: After you’ve created a private store, you can’t change the permissions you’ve defined, so you’ll always have to call the

CreateOrOpenAsync()

method with the same parameters.

Creating Contacts

A contact is defined by the StoredContact class, which is a bit different from the Contact class we’ve previously seen. In this case, the only properties that are directly exposed are GivenName and FamilyName. All the other properties can be accessed by calling the GetPropertiesAsync() method of the StoredContact class, which returns a collection of type Dictionary<string, object>.

Every item of the collection is identified by a key (the name of the contact’s property) and an object (the value). To help developers access the properties, all the available keys are stored in an enum object named KnownContactProperties. In the following sample, we use the key KnowContactProperties.Email to store the user’s email address.

Tip: Since the

ContactStore

is a dictionary, two values cannot have the same key. Before adding a new property to the contact, you’ll have to make sure that it doesn’t exist yet; otherwise, you’ll need to update the existing one.

The StoredContact class also supports a way to store custom information by accessing the extended properties using the GetExtendedPropertiesAsync() method. It works like the standard properties, except that the property key is totally custom. These kind of properties won’t be displayed in the People Hub since Windows Phone doesn’t know how to deal with them, but they can be used by your application.

In the following sample, we add new custom information called MVP Category:

Searching for Contacts

Searching contacts in the private contact book is a little tricky because there’s no direct way to search a contact for a specific field.

Searches are performed using the ContactQueryResult class, which is created by calling the CreateContactQuery() method of the ContactStore object. The only available operations are GetContactsAsync(),which returns all the contacts, and GetContactCountAsync(),which returns the number of available contacts.

You can also define in advance which fields you’re going to work with, but you’ll still have to use the GetPropertiesAsync() method to extract the proper values. Let’s see how it works in the following sample, in which we look for a contact whose email address is info@qmatteoq.com:

You can define which fields you’re interested in by creating a new ContactQueryOptions object and adding it to the DesiredFields collection. Then, you can pass the ContactQueryOptions object as a parameter when you create the ContactQueryResult one. As you can see, defining the fields isn’t enough to get the desired result. We still have to query each contact using the GetPropertiesAsync() method to see if the information value is the one we’re looking for.

The purpose of the ContactQueryOptions class is to prepare the next query operations so they can be executed faster.

Updating and Deleting Contacts

Updating a contact is achieved in the same way as creating new one: after you’ve retrieved the contact you want to edit, you have to change the required information and call the SaveAsync() method again, as in the following sample:

After we’ve retrieved the user whose email address is info@qmatteoq.com, we change it to mail@domain.com, and save it.

Deletion works in a similar way, except that you’ll have to deal with the contact’s ID, which is a unique identifier that is automatically assigned by the store (you can’t set it; you can only read it). Once you’ve retrieved the contact you want to delete, you have to call the DeleteContactAsync() method on the ContactStore object, passing as parameter the contact ID, which is stored in the Id property of the StoredContact class.

In the previous sample, after we’ve retrieved the contact with the email address info@qmatteoq.com, we delete it using its unique identifier.

Dealing With Remote Synchronization

When working with custom contact sources, we usually don’t simply manage local contacts, but data that is synced with a remote service instead. In this scenario, you have to keep track of the remote identifier of the contact, which will be different from the local one since, as previously mentioned, it’s automatically generated and can’t be set.

For this scenario, the StoredContact class offers a property called RemoteId to store such information. Having a RemoteId also simplifies the search operations we’ve seen before. The ContactStore class, in fact, offers a method called FindContactByRemoteIdAsync(), which is able to retrieve a specific contact based on the remote ID as shown in the following sample:

There’s one important requirement to keep in mind: the RemoteId property’s value should be unique across any application installed on the phone that uses a private contact book; otherwise, you’ll get an exception.

In this article published by Microsoft, you can see an implementation of a class called RemoteIdHelper that offers some methods for adding random information to the remote ID (using a GUID) to make sure it’s unique.

Taking Advantage of Kid's Corner

Kid’s Corner is an interesting and innovative feature introduced in Windows Phone 8 that is especially useful for parents of young children. Basically, it’s a sandbox that we can customize. We can decide which apps, games, pictures, videos, and music can be accessed.

As developers, we are able to know when an app is running in Kid’s Corner mode. This way, we can customize the experience to avoid providing inappropriate content, such as sharing features.

Taking advantage of this feature is easy; we simply check the Modes property of the ApplicationProfile class, which belongs to the Windows.Phone.ApplicationModel namespace. When it is set to Default, the application is running normally. If it’s set to Alternate, it’s running in Kid’s Corner mode.


Speech APIs: Let's Talk With the Application

Speech APIs are one of the most interesting new features added in Windows Phone 8. From a user point of view, vocal features are managed in the Settings page. The Speech section lets users configure all the main settings like the voice type, but most of all, it’s used to set up the language they want to use for the speech services. Typically, it’s set with the same language of the user interface, and users have the option to change it by downloading and installing a new voice pack. It’s important to understand how speech services are configured, because in your application, you’ll be able to use speech recognition only for languages that have been installed by the user.

The purpose of speech services is to add vocal recognition support in your applications in the following ways:

Enable users to speak commands to interact with the application, such as opening it and executing a task.

Enable text-to-speech features so that the application is able to read text to users.

Enable text recognition so that users can enter text by dictating it instead of typing it.

In this section, we’ll examine the basic requirements for implementing all three modes in your application.


Voice Commands

Voice commands are a way to start your application and execute a specific task regardless of what the user is doing. They are activated by tapping and holding the Start button. Windows Phone offers native support for many voice commands, such as starting a phone call, dictating email, searching via Bing, and more.

The user simply has to speak a command; if it’s successfully recognized, the application will be opened and, as developers, we’ll get some information to understand which command has been issued so that we can redirect the user to the proper page or perform a specific operation.

Voice commands are based on VCD files, which are XML files that are included in your project. Using a special syntax, you’ll be able to define all the commands you want to support in your application and how the application should behave when they are used. These files are natively supported by Visual Studio. If you right-click on your project and choose Add new item, you’ll find a template called VoiceCommandDefinition in the Windows Phone section.

The following code sample is what a VCD file looks like:

A VCD file can contain one or more CommandSet nodes, which are identified by a Name and a specific language (the xml:lang attribute). The second attribute is the most important one. Your application will support voice commands only for the languages you’ve included in CommandSet in the VCD file (the voice commands’ language is defined by users in the Settings page). You can have multiple CommandSet nodes to support multiple languages.

Each CommandSet can have a CommandPrefix, which is the text that should be spoken by users to start sending commands to our application. If one is not specified, the name of the application will automatically be used. This property is useful if you want to localize the command or if your application’s title is too complex to pronounce. You can also add an Example tag, which contains the text displayed by the Windows Phone dialog to help users understand what kind of commands they can use.

Then, inside a CommandSet, you can add up to 100 commands identified by the Command tag. Each command has the following characteristics:

A unique name, which is set in the Name attribute.

The Example tag shows users sample text for the current command.

ListenFor contains the text that should be spoken to activate the command. Up to ten ListenFor tags can be specified for a single command to cover variations of the text. You can also add optional words inside square brackets. In the previous sample, the AddNote command can be activated by pronouncing both “add a new note” or “and add new note.”

Feedback is the text spoken by Windows Phone to notify users that it has understood the command and is processing it.

NavigateTarget can be used to customize the navigation flow of the application. If we don’t set it, the application will be opened to the main page by default. Otherwise, as in the previous sample, we can redirect the user to a specific page. Of course, in both cases we’ll receive the information about the spoken command; we’ll see how to deal with them later.

Once we’ve completed the VCD definition, we are ready to use it in our application.

Note: To use speech services, you’ll need to enable the ID_CAP_SPEECH_RECOGNITION option in the manifest file.

Commands are embedded in a Windows Phone application by using a class called VoiceCommandService, which belongs to the Windows.Phone.Speech.VoiceCommands namespace. This static class exposes a method called InstallCommandSetFromFileAsync(), which requires the path of the VCD file we’ve just created.

The file path is expressed using a Uri that should start with the ms-appx:/// prefix. This Uri refers to the Visual Studio project’s structure, starting from the root.

Phrase Lists

A VCD file can also contain a phrase list, as in the following sample:

Phrase lists are used to manage parameters that can be added to a phrase using braces. Each PhraseList node is identified by a Label attribute, which is the keyword to include in the braces inside the ListenFor node. In the previous example, users can say the phrase “open the note” followed by any of the numbers specified with the Item tag inside the PhraseList. You can have up to 2,000 items in a single list.

The previous sample is useful for understanding how this feature works, but it’s not very realistic; often the list of parameters is not static, but is dynamically updated during the application execution. Take the previous scenario as an example: in a notes application, the notes list isn’t fixed since users can create an unlimited number of notes.

The APIs offer a way to keep a PhraseList dynamically updated, as demonstrated in the following sample:

First, you have to get a reference to the current command set by using the VoiceCommandService.InstalledCommandSets collection. As the index, you have to use the name of the set that you’ve defined in the VCD file (the Name attribute of the CommandSet tag). Once you have a reference to the set, you can call the UpdatePhraseListAsync() to update a list by passing two parameters:

the name of the PhraseList (set using the Label attribute)

the collection of new items, as an array of strings

It’s important to keep in mind that the UpdatePhraseListAsync() method overrides the current items in the PhraseList, so you will have to add all the available items every time, not just the new ones.

Intercepting the Requested Command

The command invoked by the user is sent to your application with the query string mechanism discussed earlier in this series. When an application is opened by a command, the user is redirected to the page specified in the Navigate node of the VCD file. The following is a sample URI:

The voiceCommandName parameter contains the spoken command, while the reco parameter contains the full text that has been recognized by Windows Phone.

If the command supports a phrase list, you’ll get another parameter with the same name of the PhraseList and the spoken item as a value. The following code is a sample URI based on the previous note sample, where the user can open a specific note by using the OpenNote command:

Using the APIs we saw earlier in this series, it’s easy to extract the needed information from the query string parameters and use them for our purposes, like in the following sample:

We use a switch statement to manage the different supported commands that are available in the NavigationContext.QueryString collection. If the user is trying to open a note, we also get the value of the number parameter.

Working With Speech Recognition

In the beginning of this section, we talked about how to recognize commands that are spoken by the user to open the application. Now it’s time to see how to do the same within the app itself, to recognize commands and allow users to dictate text instead of typing it (a useful feature in providing a hands-free experience).

There are two ways to start speech recognition: by providing a user interface, or by working silently in the background.

In the first case, you can provide users a visual dialog similar to the one used by the operating system when holding the Start button. It’s the perfect solution to manage vocal commands because you’ll be able to give both visual and voice feedback to users.

This is achieved by using the SpeechRecognizerUI class, which offers four key properties to customize the visual dialog:

ListenText is the large, bold text that explains to users what the application is expecting.

Example is additional text that is displayed below the ListenText to help users better understand what kind of speech the application is expecting.

ReadoutEnabled is a Boolean property; when it’s set to true, Windows Phone will read the recognized text to users as confirmation.

ShowConfirmation is another Boolean property; when it’s set to true, users will be able to cancel the operation after the recognition process is completed.

The following sample shows how this feature is used to allow users to dictate a note. We ask users for the text of the note and then, if the operation succeeded, we display the recognized text.

Notice how the recognition process is started by calling the RecognizeWithUIAsync() method, which returns a SpeechRecognitionUIResult object that contains all the information about the operation.

To silently recognize text, less code is needed since fewer options are available than were used for the dialog. We just need to start listening for the text and understand it. We can do this by calling the RecognizeAsync() method of the SpeechRecognizer class. The recognition result will be stored in a SpeechRecognitionResult object, which is the same that was returned in the RecognitionResult property by the RecognizeWithUIAsync() method we used previously.

Using Custom Grammars

The code we’ve seen so far is used to recognize almost any word in the dictionary. For this reason, speech services will work only if the phone is connected to the Internet since the feature uses online Microsoft services to parse the results.

This approach is useful when users talk to the application to dictate text, as in the previous samples with the note application. But if only a few commands need to be managed, having access to all the words in the dictionary is not required. On the contrary, complete access can cause problems because the application may understand words that aren’t connected to any supported command.

For this scenario, the Speech APIs provide a way to use a custom grammar and limit the number of words that are supported in the recognition process. There are three ways to set a custom grammar:

using only the available standard sets

manually adding the list of supported words

storing the words in an external file

Again, the starting point is the SpeechRecognizer class, which offers a property called Grammars.

To load one of the predefined grammars, use the AddGrammarFromPredefinedType() method, which accepts as parameters a string to identify it (you can choose any value) and the type of grammar to use. There are two sets of grammars: the standard SpeechPredefinedGrammar.Dictation, and SpeechPredefinedGrammar.WebSearch, which is optimized for web related tasks.

In the following sample, we recognize speech using the WebSearch grammar:

Even more useful is the ability to allow the recognition process to understand only a few selected words. We can use the AddGrammarFromList() method offered by the Grammars property, which requires the usual identification key followed by a collection of supported words.

In the following sample, we set the SpeechRecognizer class to understand only the words “save” and “cancel”.

If the user says a word that is not included in the custom grammar, the Text property of the SpeechRecognitionResult object will be empty. The biggest benefit of this approach is that it doesn’t require an Internet connection since the grammar is stored locally.

The third and final way to load a grammar is by using another XML definition called Speech Recognition Grammar Specification (SRGS). You can read more about the supported tags in the official documentation by W3C.

The following sample shows a custom grammar file:

The file describes both the supported words and the correct order that should be used. The previous sample shows the supported commands to manage notes in an application, like “Open the note” or “Load a reminder,” while a command like “Reminder open the” is not recognized.

Visual Studio 2012 offers built-in support for these files with a specific template called SRGS Grammar that is available when you right-click your project and choose Add new item.

Once the file is part of your project, you can load it using the AddGrammarFromUri() method of the SpeechRecognizer class that accepts as a parameter the file path expressed as a Uri, exactly as we’ve seen for VCD files. From now on, the recognition process will use the grammar defined in the file instead of the standard one, as shown in the following sample:

Using Text-to-Speech (TTS)

Text-to-speech is a technology that is able to read text to users in a synthesized voice. It can be used to create a dialogue with users so they won’t have to watch the screen to interact with the application.

The basic usage of this feature is really simple. The base class to interact with TTS services is SpeechSynthesizer, which offers a method called SpeakTextAsync(). You simply have to pass to the method the text that you want to read, as shown in the following sample:

Moreover, it’s possible to customize how the text is pronounced by using a standard language called Synthesis Markup Language (SSML), which is based on the XML standard. This standard provides a series of XML tags that defines how a word or part of the text should be pronounced. For example, the speed, language, voice gender, and more can be changed.

The following sample is an example of an SSML file:

This code features three sample SSML tags: voice for simulating the voice’s age, break to add a pause, and prosody to set the reading speed using the rate attribute.

There are two ways to use an SSML definition in your application. The first is to create an external file by adding a new XML file in your project. Next, you can load it by passing the file path to the SpeakSsmlFromUriAsync() method of the SpeechSynthesizer class, similar to how we loaded the VCD file.

Another way is to define the text to be read directly in the code by creating a string that contains the SSML tags. In this case, we can use the SpeakSsmlAsync() method which accepts the string to read as a parameter. The following sample shows the same SSML definition we’ve been using, but stored in a string instead of an external file.

You can learn more about the SSML definition and available tags in the official documentation provided by W3C.

Data Sharing

Data sharing is a new feature introduced in Windows Phone 8 that can be used to share data between different applications, including third-party ones.

There are two ways to manage data sharing:

File sharing: The application registers an extension such as .log. It will be able to manage any file with the registered extension that is opened by another application (for example, a mail attachment).

Protocol sharing: The application registers a protocol such as log:. Other applications will be able to use it to send plain data like strings or numbers.

In both cases, the user experience is similar:

If no application is available on the device to manage the requested extension or protocol, users will be asked if they want to search the Store for one that can.

If only one application is registered for the requested extension or protocol, it will automatically be opened.

If multiple applications are registered for the same extension or protocol, users will be able to choose which one to use.

Let’s discuss how to support both scenarios in our application.

Note: There are some file types and protocols that are registered by the system, like Office files, pictures, mail protocols, etc. You can’t override them; only Windows Phone is able to manage them. You can see a complete list of the reserved types in the

MSDN documentation

.

File Sharing

File sharing is supported by adding a new definition in the manifest file that notifies the operating system which extensions the application can manage. As in many other scenarios we’ve previously seen, this modification is not supported by the visual editor, so we’ll need to right-click the manifest file and choose the View code option.

The extension is added in the Extensions section, which should be defined under the Token one:

Every supported file type has its own FileTypeAssociation tag, which is identified by the Name attribute (which should be unique). Inside this node are two nested sections:

Logos is optional and is used to support an icon to visually identify the file type. Three different images are required, each with a different resolution: 33 × 33, 69 × 69, and 176 × 176. The icons are used in various contexts, such as when the file is received as an email attachment.

SupportedFileTypes is required because it contains the extensions that are going to be supported for the current file type. Multiple extensions can be added.

The previous sample is used to manage the .log file extension in our application.

When another application tries to open a file we support, our application is opened using a special URI:

The fileToken parameter is a GUID that univocally identifies the file—we’re going to use it later.

To manage the incoming URI, we need to introduce the UriMapper class we talked about earlier in this series. When we identify this special URI, we’re going to redirect the user to a specific page of the application that is able to interact with the file.

The following sample shows what the UriMapper looks like:

If the starting Uri contains the FileTypeAssociation keyword, it means that the application has been opened due to a file sharing request. In this case, we need to identify the opened file’s extension. We extract the fileToken parameter and, by using the GetSharedFileName() of the SharedAccessManager class (which belongs to the Windows.Phone.Storage namespace), we retrieve the original file name.

By reading the name, we’re able to identify the extension and perform the appropriate redirection. In the previous sample, if the extension is .log, we redirect the user to a specific page of the application called LogPage.xaml. It’s important to add to the Uri the fileToken parameter as a query string; we’re going to use it in the page to effectively retrieve the file. Remember to register the UriMapper in the App.xaml.cs file, as explained earlier in this series.

Tip: The previous UriMapper shows a full example that works when the application supports multiple file types. If your application supports just one extension, it’s not needed to retrieve the file name and identify the file type. Since the application can be opened with the special URI only in a file sharing scenario, you can immediately redirect the user to the dedicated page.

Now it’s time to interact with the file we received from the other application. We’ll do this in the page that we’ve created for this purpose (in the previous sample code, it’s the one called LogPage.xaml).

We’ve seen that when another application tries to open a .log file, the user is redirected to the LogPage.xaml page with the fileToken parameter added to the query string. We’re going to use the OnNavigatedTo event to manage this scenario:

Again we use the SharedStorageAccessManager class, this time by invoking the CopySharedFileAsync() method. Its purpose is to copy the file we received to the local storage so that we can work with it.

The required parameters are:

A StorageFolder object, which represents the local storage folder in which to save the file (in the previous sample, we save it in the root).

The name of the file.

The behavior to apply in case a file with the same name already exists (by using one of the values of the NameCollisionOption enumerator).

The GUID that identifies the file, which we get from the fileToken query string parameter.

Once the operation is completed, a new file called file.log will be available in the local storage of the application, and we can start playing with it. For example, we can display its content in the current page.

How to Open a File

So far we’ve seen how to manage an opened file in our application, but we have yet to discuss how to effectively open a file.

The task is easily accomplished by using the LaunchFileAsync() method offered by the Launcher class (which belongs to the Windows.System namespace). It requires a StorageFile object as a parameter, which represents the file you would like to open.

In the following sample, you can see how to open a log file that is included in the Visual Studio project:

Protocol Sharing

Protocol sharing works similarly to file sharing. We’re going to register a new extension in the manifest file, and we’ll deal with the special URI that is used to launch the application.

Let’s start with the manifest. In this case as well, we’ll have to add a new element in the Extensions section that can be accessed by manually editing the file through the View code option.

The most important attribute is Name, which identifies the protocol we’re going to support. The other two attributes are fixed.

An application that supports protocol sharing is opened with the following URI:

The best way to manage it is to use a UriMapper class, as we did for file sharing. The difference is that this time, we’ll look for the encodedLaunchUri parameter. However, the result will be the same: we will redirect the user to the page that is able to manage the incoming information.

In this scenario, the operation is simpler. We extract the value of the parameter LogId and pass it to the LogPage.xaml page. Also, we have less work to do in the landing page; we just need to retrieve the parameter’s value using the OnNavigatedTo event, and use it to load the required data, as shown in the following sample:

How to Open a URI

Similar to file sharing, other applications can interact with ours by using the protocol sharing feature and the Launcher class that belongs to the Windows.System namespace.

The difference is that we need to use the LaunchUriAsync() method, as shown in the following sample:

Conclusion

In this tutorial, we’ve e

Show more