31 Days of Mango | Now In eBook Format!

The entire series, 31 Days of Mango, is now available in e-book format for Kindle and Nook!  If you would like to read all of these articles on-the-go, while supporting the developers that wrote them, they are now available for in the Nook and Kindle stores!

The proceeds of this book will be distributed amongst all of the amazing authors that contributed to this series of articles: Jeff Blankenburg, Jared Bienz, Samidip Basu, Jerrel Blankenship, Dave Bost, Michael Collier, Matt Eland, Jeff Fansler, Gary Johnson, Parag Joshi, Chris Koenig, Doug Mair, and Chris Woodruff.

nook_logoAmazon_Kindle_Logo

 

 

Cover

I also spent the summer writing a physical, printed book with Jesse Liberty, titled Migrating to Windows Phone.  If you would like to check it out, you can find it at your favorite bookseller.  [It will also be available as an e-book, but won’t be available until later this month.]

Migrating to Windows Phone

 

amazon.com_[1]

 

nook_logo

 

 

 


31 Days of Mango | Day #31: Promoting Your App

Day31-PromotingYourApplicationDay30-LocalDatabaseDay29-GlobalizationDay28-MediaLibraryDay27-MicrophoneAPI

This article is Day #31 in a series called 31 Days of Mango.

Getting users to find your application might seem like something that’s out of your hands, but you’re wrong. There are plenty of things you can do to drive awareness of your application. This section focuses on a few best practices you should utilize for every application that you create.

The First Week Is Vital

Unless your app becomes a runaway sensation, it’s highly likely that your app’s first week in the marketplace will also see your highest number of daily downloads. Getting exposure in the New category is a one time opportunity, and you need to make sure that you leverage this in a way that will make your app shine for much longer than a few days. Ultimately, your goal is to catapault from the New category to the Top Apps category. The 4-5 days that you will wait for your application to be approved should be spent executing a specific strategy for making the public aware of your application.

Linking To Your Application

When you first submit your application to the Marketplace, even before the app is approved, you are assigned a deep link that you can use to direct people to your app using a standard web URL. Here’s an example of the deep link to one of my applications, MathMaster:

http://windowsphone.com/s?appid=f08521cd-1cff-df11-9264-00237de2db9e

This link takes you to a webpage that will attempt to launch the Zune software on the user’s machine, and then direct them to the page for your app in the Marketplace. This link will not work until your application is approved. We recommend using this link everywhere you can, especially on the custom website you created for your apps. You were planning on doing that, right?

Creating a Web Portal for Your Apps

An important thing that you should have learned from the Marketplace walkthrough in Day #27 of the original 31 Days of Windows Phone was that your ability to discuss your apps is pretty limited. A few screenshots, and approximately 2,000 characters is all you have. By creating a website for your applications, you create several new opportunities for yourself.

1. You can create real connections with your users. The Windows Phone marketplace doesn’t give you any indication who your users are. A website allows you to interact with your fans.

2. You can provide a rich amount of information about your app, including videos and other promotional content that might make your app more appealing.

3. You can cross-sell your applications. The Marketplace doesn’t always do a great job at promoting your other applications to potential customers, so leverage your website to make that happen.

4. Your app is now discoverable by people that aren’t actively looking for it in the Marketplace.

5. This website doesn’t have to be a website at all. There’s nothing wrong with creating a page on Facebook or another social network that you can customize. The ultimate goal of this process is to provide a destination for your fans, so that they can spread the word about your awesome app.

If you would like an awesome template for building a custom web page for your application, check out the Windows Phone 7 App Site template on CodePlex.  It’s a customizable page that looks great, uses your application screen shots, allows your users to provide feedback, and gives them plenty of ways to learn more about your application.  Here’s a screenshot of the template:

image

Create A Walkthrough Video of Your App

One of the important features your website should include is a video walkthrough of your app. Screenshots in the marketplace are good, but allowing a user to see the actual experience in a controlled way will always provide them with more information. Our recommendation is to use a video screen capture tool like TechSmith’s Camtasia. Camtasia makes it easy to not only capture the video feed from the emulator, but to edit the results, add background music, and introduction information before and after the video. There are probably plenty of tools that will do this for you, but in our experience, Camtasia is the perfect tool for the job. You can see an example of my MathMaster video on YouTube here:

http://youtu.be/uMlyUn3sgJU

Have fun with it. Your video can add a level of excitement to your app that screenshots can never provide. Now that we’ve focused on websites and videos, let’s discuss the things you can do inside your application to help promote it.

Generating Reviews of Your Application

Reviews can be the deciding factor as to whether or not your application gets the downloads you’re looking for. Unfortunately, there’s not a built-in mechanism for reminding users to review your app. You need to do this yourself. We recommend making it a fun addition to your application rather than an annoyance to your user.

One idea we recommend is to make it an achievement within your app. Litter fun little surprises throughout your application, and you’ll hook an otherwise passive user. Give points for reading the credits of the app. Give more for using the app 10 times. By adding achievements to any application, you’ll find that your users will find themselves coming back again and again. You might also unlock a specific piece of functionality that would otherwise be unavailable when they review your app.

A second idea is to count the number of times your user has launched your application, and prompt them at the 2nd, 5th, and 10th times to review your application. Ask gently. You don’t want to annoy the user, but you do want their review. You can even use the MarketplaceReviewTask to take them directly to the review page for your application.

Great reviews generate more traffic. Oftentimes, a star review can be just as valuable as a written one. The average star rating (1-5) is displayed everywhere your application is, so a high rating often generates more traffic. Encouraging your users to leave a review will have a positive effect on your application’s download rates.

Cross-Selling Your Applications from Each Other

Within your app, you should provide a place where the user can find information about your company, support contacts, and other data like version number. In this place, or certainly in a more prominent location, you have an opportunity to promote the other applications you’ve created. Use your icons. Use the deep links or the MarketplaceDetailTask launcher. Provide a simple way for your user to find and download your other application offerings.

If you really want to get fancy, create an XML file on your webserver that contains all of the information about your apps, and consume this in your apps to create the list of your applications. This way, when you add a new app to your catalog, you won’t have to update all of your apps just to do this cross-promotion.

Summary

There are plenty of things you need to do in order to get your application ready, after you’ve finished your application. Make sure that you’ve considered your promotion strategy before you push the final Submit button on your app. Building a community around your application will only help to make your audience grow, because enthusiastic users are also powerful evangelists of your efforts.

If you’ve taken the time to create an amazing new application for Windows Phone, you need to be certain that it’s going to have the potential impact you’re hoping for. Focusing on monetizing, promotion, and reviews is almost as important your app.

This is the final post in this series.  I hope you’ve enjoyed it as much as my guest authors and I did writing it.  Thank you for reading all of the posts, and if you haven’t already…

toolsbutton

31 Days of Mango | Day #30: Local Database

Day30-LocalDatabaseDay29-GlobalizationDay28-MediaLibraryDay27-MicrophoneAPIDay26-BackgroundFileTransfers

This article is Day #30 in a series called 31 Days of Mango, and was written by guest author Chris Woodruff.  Chris can be reached on Twitter at @cwoodruff.

What is a Local Database?

In the original version of Windows Phone 7, we could save data but it took either custom code or using third party databases like SterlingDB to have the relational data repository that some applications need. This limited the types of applications some developers could produce for users.

In Windows Phone 7 Mango, developers still have isolated storage to keep data and information stored for their applications but now have SQL CE as a relational storage feature to created even better applications for Windows Phone.

Like other database solutions for the original Windows Phone 7, the native SQL CE database built into Mango has it data stored in the device’s Isolated Storage. You can learn more about Isolated Storage here. Microsoft also did not create new ways to work with the data on the phone and instead implemented LINQ to SQL for all database operations. LINQ to SQL is used to do all functions for the application when dealing with data including creating the data, populating data into the database, getting data and finally saving and deleting data.

A good tutorial for LINQ to SQL is here on MSDN.

Setting up a Local Database for your Mango Application

Like all starting points for Windows Phone 7, we will start with creating the Windows Phone Databound Application project within Visual Studio 2010.

clip_image002

We could have started with just the Windows Phone Application project but I like the additional features that the Databound project gives you to allow your application to have better design patterns like Model-View-ViewModel (MVVM).

Next we will update the MainPage of the project to allow for the data to be added to the database. Our data example will be collecting ideas that we all have and need to remember. We will not go into much detail about the design of the MainPage but here is the XAML to get the look and feel for our Idea collector.

<phone:PhoneApplicationPage
   x:Class="_31DaysMangoStorage.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
   mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
   d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
   FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait" Orientation="Portrait"
   shell:SystemTray.IsVisible="True">

    <!–LayoutRoot is the root grid where all page content is placed.–>
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!–TitlePanel contains the name of the application and page title.–>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="31 Days of Mango" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Idea Tracker" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!–ContentPanel – place additional content here.–>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <!– Bind the list box to the observable collection. –>
            <ListBox x:Name="toDoItemsListBox" ItemsSource="{Binding IdeaItems}"
                    Grid.Row="0" Margin="12, 0, 12, 0" Width="440">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid HorizontalAlignment="Stretch" Width="440">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="100" />
                            </Grid.ColumnDefinitions>
                            <CheckBox
                               IsChecked="{Binding IsComplete, Mode=TwoWay}"
                               Grid.Column="0"
                               VerticalAlignment="Center"/>
                            <TextBlock
                               Text="{Binding ItemName}"
                               FontSize="{StaticResource PhoneFontSizeLarge}"
                               Grid.Column="1"
                               VerticalAlignment="Center"/>
                            <Button
                               Grid.Column="2"
                               x:Name="deleteTaskButton"
                               BorderThickness="0"                                
                               Margin="0"
                               Click="deleteTaskButton_Click">
                                <Image Source="appbar.delete.rest.png"/>
                            </Button>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <Grid Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <TextBox
                   x:Name="newIdeaTextBox"                    
                   Grid.Column="0"
                   Text="add new idea"
                   FontFamily="{StaticResource PhoneFontFamilyLight}"                    
                   GotFocus="newIdeaTextBox_GotFocus"/>
                <Button
                   Content="add"
                   Grid.Column="1"
                   x:Name="newIdeaAddButton"
                   Click="newIdeaAddButton_Click"/>
            </Grid>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>
 

Also to allow for your application to compile and run without doing anything the code below will be added to the MainPage.xaml.cs file inside the MainPage class implementation and after the constructor.

private void newIdeaTextBox_GotFocus(object sender, RoutedEventArgs e)
{
    // Clear the text box when it gets focus.
    newIdeaTextBox.Text = String.Empty;

}

private void newIdeaAddButton_Click(object sender, RoutedEventArgs e)
{

}

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    // Call the base method.
    base.OnNavigatedFrom(e);

}
 

Working with the Data Context

The Data Context is the point that will allow us to work with the database and also the proxy classes that represent our database tables. The data context is also a class and works against a number of “plain old CLR object” (POCO) classes that we will create for this project. The table objects that represent our database tables will contain a collection of entities for each table record stored in the database. Other details about our database are also given to us through the data context such as table keys and association mappings between tables.

Just a reminder that this local database has no connection with SQL Server 2008 R2 that is running locally on your PC or a server in your company or hosting provider and is only to hold data on your device.

There is not much to the DataContext class besides the connection string we are familiar in development and properties to each table that will exist in our database. Think of the DataContext as the “Hub” for your application’s data. The code for the sample application’s DataContext is below.

public class IdeaDataContext : DataContext
{
    // Specify the connection string as a static, used in main page and app.xaml.
    public static string DBConnectionString = "Data Source=isostore:/Ideas.sdf";

    // Pass the connection string to the base class.
    public IdeaDataContext(string connectionString)
        : base(connectionString)
    { }

    // Specify a single table for the to-do items.
    public Table<IdeaItem> IdeaItems;
}
 

Note that IdeaItem type will be detailed in the next section covering creating the Database.

Creating the Database

Unlike applications that are run from your PC or on IIS 7, databases in Windows Phone 7 Mango must be created and initialized on the first instance your app runs on the phone. We will first look at creating the classes that will represent our database tables and then look at database initialization.

For each table that we need to be built and exposed through the database on our phone for the application a new POCO needs to be created. Since these classes represent the entities that will be stored in the database let’s call them Entity classes. To begin the Entity class must adhere to the following two interfaces:

· INotifyPropertyChanged — The INotifyPropertyChanged interface is used to notify clients, typically binding clients that a property value has changed.

· INotifyPropertyChanging — The INotifyPropertyChanging interface is used to notify clients, typically binding clients that a property value is changing.

These two interfaces will allow each entity to notify the DataContext that is in the process of changing or has changed. This will then be reflected to the XAML views of our application through the binding we have set up.

The Enity class must be annotated as a Table to allow the DataContext to know how to work with it. An Entity classes must also have private and public properties for each Entity property as well as having the private property annotated to give valuable metadata about the Entity property (aka the database column). Remember to have primary key properties for each of your Entity classes.

Below is the IdeaItem Entity class that will be located in the IdeaItems table referenced in the DataContext we created before.

[Table]
public class IdeaItem : INotifyPropertyChanged, INotifyPropertyChanging
{
    private int _ideaItemId;
    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int IdeaItemId
    {
        get
        {
            return _ideaItemId;
        }
        set
        {
            if (_ideaItemId != value)
            {
                NotifyPropertyChanging("IdeaItemId");
                _ideaItemId = value;
                NotifyPropertyChanged("IdeaItemId");
            }
        }
    }

    private string _itemName;
    [Column]
    public string ItemName
    {
        get
        {
            return _itemName;
        }
        set
        {
            if (_itemName != value)
            {
                NotifyPropertyChanging("ItemName");
                _itemName = value;
                NotifyPropertyChanged("ItemName");
            }
        }
    }

    private bool _isComplete;
    [Column]
    public bool IsComplete
    {
        get
        {
            return _isComplete;
        }
        set
        {
            if (_isComplete != value)
            {
                NotifyPropertyChanging("IsComplete");
                _isComplete = value;
                NotifyPropertyChanged("IsComplete");
            }
        }
    }

    [Column(IsVersion = true)]
    private Binary _version;
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangingEventHandler PropertyChanging;
    private void NotifyPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
        {
            PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }
    }
}
 

Finally we must create the database is it does not exist. This will be done in the Application class’s constructor. You will find this in the App.xaml.cs file. The code that will be added to the end of the constructor method is as followed.

using (IdeaDataContext db = new IdeaDataContext(IdeaDataContext.DBConnectionString))
{
    if (db.DatabaseExists() == false)
    {
        db.CreateDatabase();
    }
}
 

We now have a database that has been created and initialized in application’s Isolated Storage. One more thing to remember is that local databases in Windows Phone 7 mango cannot be shared directly between apps on the phone due to the sandboxing security set up in the Windows Phone 7 Mango operating system.

LINQ to SQL Support for Windows Phone Mango

Windows Phone 7.1 SDK allows for some but not all features of LINQ to SQL inside the Windows Phone. The following are just a few things to remember when working with data and LINQ to SQL in Windows Phone 7 Mango.

· ExecuteCommand is not supported

· ADO.NET Objects (such as DataReader) are not supported

· Only Microsoft SQL Server Compact Edition (SQL CE) data types are supported

To get more limitations and features of using LINQ to SQL on Mango please read the MSDN page here.

Retrieving Data from a Local Database

To retrieve data or any data related work with the local database, we must first create the DataContext and connect to the database. This will happen in MainPage.xaml.cs through a private variable for the DataContext, an observable collection property for the ideas in the database table and in the MainPage constructor as followed.

private IdeaDataContext ideaDB;

private ObservableCollection<IdeaItem> _ideaItems;
public ObservableCollection<IdeaItem> IdeaItems
{
    get
    {
        return _ideaItems;
    }
    set
    {
        if (_ideaItems != value)
        {
            _ideaItems = value;
            NotifyPropertyChanged("IdeaItems");
        }
    }
}

public MainPage()
{
    InitializeComponent();

    ideaDB = new IdeaDataContext(IdeaDataContext.DBConnectionString);
    this.DataContext = this;
}
 

To get our ideas located in the local database we will use LINQ to SQL to query and get the collection back from the database via the DataContext.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    var ideaItemsInDB = from IdeaItem todo in ideaDB.IdeaItems
                        select todo;

    IdeaItems = new ObservableCollection<IdeaItem>(ideaItemsInDB);
    base.OnNavigatedTo(e);
}
 

The ideas are now bound and reflected in the MainPage.xaml.

clip_image003

Storing Data to a Local Database

Finally we will build the saving of our idea data to the local database. We will not send the ideas to the database until we need to increase performance. We will keep all of the ideas in the local observable collection we created as a MainPage property (IdeaItems). The addition of new ideas to the local database will take place on the button click when the new idea is added to the IdeaItems collection.

private void newIdeaAddButton_Click(object sender, RoutedEventArgs e)
{
    IdeaItem newIdea = new IdeaItem { ItemName = newIdeaTextBox.Text };

    IdeaItems.Add(newIdea);
    ideaDB.IdeaItems.InsertOnSubmit(newIdea);
}
 

As mentioned before the ideas collected from the user will not be stored in the database until the application has transitioned from the MainPage either when the user exits the application or the application moves to a new page in the application. The code for the OnNavigateFrom event for the MainPage is below.

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);
    ideaDB.SubmitChanges();
}
 

Summary

So that’s pretty much it!  You now have a simple way to create, store, and retrieve relational data in your Windows Phone applications.  How are you going to use this?

To download a full Windows Phone project that includes all of the code and concepts from this article, click the Download Code button below.

download

Tomorrow, in the final article of this series, we will cover the best practices for promoting your Windows Phone applications.  See you then!

toolsbutton

31 Days of Mango | Day #29: Globalization

Day29-GlobalizationDay28-MediaLibraryDay27-MicrophoneAPIDay26-BackgroundFileTransfersDay25-BackgroundAgents

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

Globalization versus Localization

People often get confused when discussing globalization and localization. Both deal with presenting content in a user-friendly manner across the world, but the distinction is that globalization deals with formatting elements such as times, dates, currencies and numbers in the way that the user is familiar with whereas localization involves displaying the user’s native language in the user interface. This article will cover using both techniques to build applications that can reach a large audience in the most user-friendly way possible.

We will be building a simple application over the course of this article that supports both globalization and localization. This application quickly generates an e-mail message that lets a contact know you’re running late to an appointment.

Configuring Localization Support

After creating a new C# Windows Phone project, we’ll need to do a few things to configure the application to support localization.

Defining a neutral language for the assembly

Because we’re localizing our application, we need to tell the project what the default locale is. To do this, we’ll go into the properties dialog for the project and click on “Assembly Information…” and then specify the neutral language for our assembly – that is, the language that will be used if no locale-specific resources are defined that matches the user’s locale. For this example, we’ll set our neutral language to English (United States).

clip_image002

Indicating supported culture

Next we need to tell the project what languages are supported. Visual Studio doesn’t currently expose this part of the project information, but we can easily edit it. Make sure you save all changes so any changes to the .csproj file are saved to disk before we edit the file. Next go to the project’s folder on the disk drive by right clicking on the project and selecting “Open folder in Windows Explorer”. Select the .csproj file for your application (be careful not to select the .csproj.user file) and open it with Notepad or your favorite text editor.

Look for the <SupportedCultures></SupportedCultures> element and add the culture codes of the cultures you wish to support separating each culture with a semicolon. This list should not include the neutral language of the assembly. See http://msdn.microsoft.com/en-us/library/hh202918(v=VS.92).aspx for a list of cultures supported by various versions of Windows Phone. For the purposes of this example, we’ll be supporting Spanish, simplified Chinese and French in addition to the default culture of English (United States) so our SupportedCultures node looks like:

<SupportedCultures>es-ES;zh-CN;fr-FR</SupportedCultures>

After making your changes, save the .csproj file and go back to Visual Studio. Click reload when Visual Studio prompts you that the project has changed so the changes to the project file can take effect.

Create a base resource file

Now that we have a default culture and a list of other supported cultures, we can start defining culture-specific resources. We’ll start by adding a file for default resources and move on to adding resources for specific cultures. As a localization best-practice, any user-facing string should be included in these files instead of hard-coded in XAML or a code file.

We need to add a resource file to the project that defines the default language strings for the application. To do this, we’ll right click on our project in the solution explorer and choose “Add -> New Item”. From here, we’ll add a resource file. This file can be called whatever you like, but for this example we will call it Strings.

clip_image004

Adding the file takes us into the resource editor for this resource. The resource editor contains a table with three columns: Name, Value and Comment. Name is the auto-generated code-behind name for the resource and serves as a unique key for identifying a resource. Value is the culture-specific value for this resource and is what we’ll use to store user-facing text. Comment is not used by the application but is helpful for noting what each resource means and where it’s used and can help greatly during translation to other languages. You’ll also see an access modifier at the top of the resource editor. This is internal by default but we need to change this to public so we can bind to these values in XAML later.

Here is our example after adding the appropriate strings and changing the access modifier to public:

clip_image006

Create culture specific resource files

Now that we have our default resources defined, we can begin creating customized resources for the project. We’ll start by defining the Spanish resources for this application. Control-click and drag Strings.resx in solution explorer to create a copy of String.resx then rename “Copy of Strings.resx” to “Strings.es-ES.resx” (es-ES is the culture code for Spanish). It’s important that this new file start with the same name as your previous resource file but have the matching locale at the end of it or this file will not properly map to the intended locale. Once you’ve renamed that file, open up the Strings.es-ES.resx file and modify the Value column for each resource. A good source for translations is Bing Translator, though you should verify translations with someone who understands the language before deploying. It’s important that the Name column matches between resource files so that resources can be appropriately mapped.

Once you’ve finished with this, follow the same procedure for any additional locales you wish to support being careful that all resource files have an access modifier of Public, keep the same name, and contain the appropriate culture code. It’s also important to note that the resource editor may not display certain foreign character sets correctly when copying and pasting from Bing Translator to the resource editor, but these characters should look fine on the actual device and the emulator.

clip_image008

Building the non-localized user interface

Now that we have a set of localized strings, we’d better build a user interface that can use them. Our sample application will have a few fields, an application bar and a standard header. Because we want to include dates in this example to demonstrate globalization, we will be referencing the Silverlight Toolkit for Windows Phone and using the TimePicker control contained in that assembly. This article won’t go into detail on downloading, installing and referencing the toolkit, but the toolkit is freely available and help is available online.

clip_image010

Our non-localized MainPage.xaml looks like:

<phone:PhoneApplicationPage
   x:Class="PhoneApp1.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot; xmlns:Controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
   FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
   shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsMenuEnabled="False">
            <shell:ApplicationBarIconButton IconUri="/icons/appbar.feature.email.rest.png"
                                           IsEnabled="True"
                                           Text="send"
                                           Click="HandleSendClick" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

    <!–LayoutRoot is the root grid where all page content is placed–>
    <Grid x:Name="LayoutRoot"
         Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <!–TitlePanel contains the name of the application and page title–>
        <StackPanel x:Name="TitlePanel"
                   Grid.Row="0"
                   Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle"
                      Text="I’m Running Late"
                      Style="{StaticResource PhoneTextNormalStyle}" />
            <TextBlock x:Name="PageTitle"
                      Text="Send Message"
                      Margin="9,-7,0,0"
                      Style="{StaticResource PhoneTextTitle1Style}"
                      TextWrapping="Wrap" />
        </StackPanel>
        <ScrollViewer Margin="12,0,12,0"
                     Grid.Row="1">
            <StackPanel x:Name="ContentPanel">
                <TextBlock TextWrapping="Wrap"
                          Text="To"
                          Style="{StaticResource PhoneTextSubtleStyle}" />
                <TextBox x:Name="txtTo"
                        TextWrapping="Wrap"
                        InputScope="EmailUserName" />
                <HyperlinkButton Content="Choose a contact"
                                HorizontalContentAlignment="Left"
                                Foreground="{StaticResource PhoneAccentBrush}"
                                Click="HandleChooseContactClick"
                                Margin="{StaticResource PhoneVerticalMargin}" />
                <TextBlock TextWrapping="Wrap"
                          Text="Subject"
                          Style="{StaticResource PhoneTextSubtleStyle}" />
                <TextBox x:Name="txtSubject"
                        TextWrapping="Wrap"
                        Text="I’m Running Late"
                        InputScope="Text" />
                <CheckBox x:Name="checkIncludeReason"
                         Content="Include a reason" />
                <TextBox x:Name="txtReason"
                        TextWrapping="Wrap"
                        Text="Traffic"
                        InputScope="Text"
                        IsEnabled="{Binding IsChecked, ElementName=checkIncludeReason}" />
                <CheckBox x:Name="checkIncludeETA"
                         Content="I should arrive by" />
                <Controls:TimePicker x:Name="timeArrival"
                                    IsEnabled="{Binding IsChecked, ElementName=checkIncludeETA}"
                                    Margin="0,-12,0,0" />
                <CheckBox x:Name="checkIncludeDiagnosticData"
                         Content="Include extra data" />
            </StackPanel>
        </ScrollViewer>
    </Grid>
</phone:PhoneApplicationPage>
 

Obviously this XAML contains a number of hardcoded strings which is not what we want for a localizable application. We need to get the user interface to take advantage of our resource strings.

Retrieving Resource Strings in XAML

Luckily, the resource designer we’ve been working with has already automatically generated classes for accessing these resources. Unfortunately, we can’t easily bind to these in XAML because the auto-generated Strings class has an internal constructor and static properties so we’ll need to create a resources wrapper object that exposes these in a way we can bind to.

Add a new code file to the solution called StringProvider.cs and include the following code:

namespace PhoneApp1
{
    public class StringProvider
    {
        private readonly Strings _resources = new Strings();

        public Strings Resources
        {
            get { return _resources; }
        }
    }
}
 

Now go into your App.xaml file and add a new resource to the application with an appropriate xmlns qualifier. This resource will be available across the entire application and will provide easy access to string localization. When done, our App.xaml will look like:

<Application
   x:Class="PhoneApp1.App"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;       
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:local="clr-namespace:PhoneApp1">

    <!–Application Resources–>
    <Application.Resources>
        <local:StringProvider x:Key="Strings" />
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
        <!–Required object that handles lifetime events for the application–>
        <shell:PhoneApplicationService
           Launching="Application_Launching" Closing="Application_Closing"
           Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>

</Application>
 

Now that we’ve defined our StringProvider as a resource, we can bind to it in the main page. In this case we’re binding to a sub-property on the Resources property representing the name of the resource as we defined it earlier in the resources collection and using the application StringProvider object as a binding source. For example, our page title TextBlock becomes:

<TextBlock x:Name="PageTitle" Text="{Binding Resources.PageTitleSendMessage, Source={StaticResource Strings}}" TextWrapping="Wrap" />
 

Both Blend and Visual Studio’s design surfaces should recognize this binding and display the neutral language string (the value in Strings.resx) in the designer if the project has been rebuilt since the resource was added.

When building localizable applications, be aware that in many languages resource strings will be longer than in the default locale. Because of this, it’s important that you set TextWrapping="Wrap" where applicable and use flexible layout structures such as ScrollViewers and StackPanels that can adapt to multi-line content when needed. Due to potentially long resource strings, setting SupportedOrientations="PortraitOrLandscape" on the page element is recommended where appropriate.

It’s also important to be aware that not all locales support different fonts. Your best bet for application localization is to avoid manually specifying fonts or font weights and instead relying on the built-in styles. See http://msdn.microsoft.com/en-us/library/hh202920(v=VS.92).aspx for more information.

Referring to localized strings in code behind

This approach will work for most of the strings, but Metro design guidelines require the application title at the top of the page to be in all caps and our string in the resource file uses initial caps. We could define a new resource just for the title label or write a custom to uppercase value converter for the binding, but instead we’ll just set the title in the code behind so we can demonstrate accessing localized resources from code by adding the following line to the MainPage’s constructor:

ApplicationTitle.Text = Strings.AppTitle.ToUpper(CultureInfo.CurrentCulture);

Localizing application bars

Application bar elements do not presently support binding since they’re not truly customizable Silverlight content. Instead, we’ll have to manually set the text of our ApplicationBarIconButton in the code behind by referring to the auto-generated property for our resource name on the Strings resource as follows:

public MainPage()
{
    InitializeComponent();

    // Ensure that the app title uses all caps
    ApplicationTitle.Text = Strings.AppTitle.ToUpper(CultureInfo.CurrentCulture);

    // Specify the text explicitly on the app bar using our resource string.
    var button = (ApplicationBarIconButton)ApplicationBar.Buttons[0];
    button.Text = Strings.ButtonSend;

    // By default, we’re going to be 15 minutes later than now
    timeArrival.Value = DateTime.Now.AddMinutes(15);
}
 

We now have a localized application. Testing the application in the emulator using French language settings results in the following:

clip_image012

Supporting Globalization

Now that we have a localizable application, let’s get into the globalization side of things. Since globalization deals with respecting a user’s cultural settings, it’s important to provide the correct IFormatProvider to various string formatting methods whenever appropriate. Thankfully, .NET provides CultureInfo.CurrentCulture which represents the user’s current cultural settings and can be used for formatting strings for the user interface. When doing standard comparisons or dealing with serialization or other non-user-facing operations, it’s important to use CultureInfo.InvariantCulture to ensure your app works properly in all culture settings.

Unlike localization, you don’t have to do anything to support a particular culture and the .NET framework will take care of most culture formatting operations for you. It is still a best practice to provide the appropriate format strings and specify CultureInfo.CurrentCulture as an IFormatProvider where appropriate.

For example, the code our application uses to generate an e-mail makes explicit use of the CurrentCulture and format strings:

private void HandleSendClick(object sender, EventArgs e)
{
    // Build the E-Mail body from the user’s selections
    var body = new StringBuilder();
    body.AppendLine(Strings.EmailHeader);

    // Include reason if applicable
    var culture = CultureInfo.CurrentCulture;
    if (checkIncludeReason.IsChecked == true)
    {
        body.AppendLine();
        body.AppendLine(string.Format(culture, "{0}: {1}", Strings.EmailReason, txtReason.Text));
    }

    // Include eta if applicable
    if (checkIncludeETA.IsChecked == true)
    {
        body.AppendLine();
        // Since we’ve specified our ValueFormatString for the Time Picker, we can just rely on the ValueString here.
        body.AppendLine(string.Format(culture, "{0}: {1}", Strings.CheckShouldArriveBy, timeArrival.ValueString));
    }

    // Include extra globalization examples if applicable
    if (checkIncludeDiagnosticData.IsChecked == true)
    {
        body.AppendLine();
        // this is the standardized culture name such as en-US or zh-CH
        body.AppendLine(culture.Name);
        body.AppendLine(string.Format(culture, "pi: {0}", Math.PI));
        body.AppendLine(string.Format(culture, "number: {0}", -1));
        body.AppendLine(string.Format(culture, "currency: {0:c}", 4200.00));
        body.AppendLine(string.Format(culture, "date: {0:D}", DateTime.Today));
        body.AppendLine(string.Format(culture, "time: {0:t}", DateTime.Now));
    }

    // Now that we have our message body, do something with it. What we do depends on what we’re running on.
    if (Microsoft.Devices.Environment.DeviceType == DeviceType.Emulator)
    {
        // The emulator doesn’t currently support sending E-Mails so we’ll just output the text to a message box
        MessageBox.Show(body.ToString());
    }
    else
    {
        // Compose the E-Mail and show it to the user to preview before sending
        var task = new EmailComposeTask {Subject = txtSubject.Text, To = txtTo.Text, Body = body.ToString()};
        task.Show();
    }
}
 

Since globalization is separate from localization, running the app in a language without locale-specific strings will result in properly globalized values such as these German settings in the image below:

clip_image014

Specifying format strings in XAML

Occasionally you’ll want to be able to specify a format string in XAML either as a parameter to a value converter or as a property on a built in control. In our example we’ll explicitly set the format string of our TimePicker to the short time format for the current culture (“t”). To do this, we prefix our format string with a pair of braces as shown here:

<Controls:TimePicker x:Name="timeArrival" ValueStringFormat="{}{0:t}" />
 

It’s also possible to set this in code behind either as

var info = CultureInfo.CurrentCulture.DateTimeFormat;
timeArrival.ValueStringFormat = "{0:" + info.ShortTimePattern + "}";
 

or, more concisely:

timeArrival.ValueStringFormat = "{0:t}";
 

Testing for different cultures

By this point we’ve built a fully functional app that supports globalization and localization. You may be wondering how to test applications for different locales. Actual Windows Phone devices may not allow you to change your phone’s display language, but thankfully Microsoft provided this capability in the emulator.

To access these settings, go into the emulator’s applications menu on the start screen and choose the settings app. From there click on region+language on the system pivot item. clip_image016

The region & language screen allows you to customize the display language on the phone by setting the Display language picker box to the language you want to test and then clicking on the “tap here to accept changes” hyperlink. Doing so will reboot the emulator’s image of the Windows Phone operating system and apply the language and globalization settings you’ve chosen. It can be confusing to use the settings pages in a language you don’t know to change regional settings so it’s a good idea to study the layout of the screen before applying your changes. Once the emulator reboots, launching your application in the emulator will allow you to verify that the app respects the user’s language and cultural settings.

Deployment Considerations

When deploying an application that supports different languages and cultures, be sure to opt-in to distribution in the markets you support either by selecting worldwide distribution when publishing your app and setting the prices or by selecting the individual locales that you explicitly intend to support.

Summary

You now know how to create an application from start to finish that will offer the best experience by providing a properly globalized and localized application to the global audience that uses Windows Phone.

To download a full Windows Phone project that uses all of the code and examples from above, click the Download Code button below.

download

Tomorrow, we are going back to data, and we’re going to cover how to use a local database in your application.  See you then!

toolsbutton

31 Days of Mango | Day #28: Media Library

Day28-MediaLibraryDay27-MicrophoneAPIDay26-BackgroundFileTransfersDay25-BackgroundAgentsDay24-ProfilerTool

This article is Day #28 in a series called 31 Days of Mango, and was written by guest author Jeff Fansler. Jeff can be reached on Twitter at @fanzoo.

Today we are going to take a look at the MediaLibrary class that is part of the Microsoft.Xna.Framework.Media namespace. As the name suggests, this class gives us access into the users Media Library. A Media Library on Windows Phone stores pictures and music. By using the Media Library you can integrate this content into your own applications. There are several reasons a developer may want to do this. Here are a few ideas:

  • To show the user a list of songs and let them select the background music while using your app.
  • To allow the user to download their images from a service (i.e. Flickr) and add them to the Media Library.
  • To use music artist or genre data from the Media Library to make suggestions on other similar content the user may be interested in.

In order to show how to use the Media Library I’ve created a sample application. This app will list all the songs that are in the user’s Media Library, play a song when the user selects a song, and allow the user to select an image from the Media Library to use as the background. The app uses the Media Library to get a list of songs and it also saves an image to the Media Library for the user.

clip_image002[7]

Saving an Image to the Media Library

In the sample app I have added image1.jpg as a resource. It’s an awesome image and I’m sure all of the users are going to want it so we are going to save this image to the Media Library. The sample app saves this image in the Application_Launching method in the App.xaml.cs. Here is the code that does this work:

var library = new MediaLibrary();
var image = library.Pictures.Where(p => p.Name == imageName).SingleOrDefault();

if (image == null)
{
    var resource =
        Application
        .GetResourceStream(new Uri(string.Format("/31DaysMediaLibrary;component/Images/{0}",
                                    imageName),
                            UriKind.Relative));
    var bitmap = new BitmapImage();
    bitmap.SetSource(resource.Stream);

    // Save the image to the camera roll or saved pictures album.
    library.SavePicture(imageName, bitmap.ToStream());
}
 

Most of this code is simply working with loading the image. There are a few important lines here that are using the Media Library. Let’s take a closer look at a few of these lines.

var library = new MediaLibrary();
 

This line creates a new MediaLibrary class. This is what will give you access to the Media Library properties and methods.

var image = library.Pictures.Where(p => p.Name == imageName).SingleOrDefault();
 

This line searches the library for any pictures that are saved with the imageName. If that image exists already, the code does not save it again.

library.SavePicture(imageName, bitmap.ToStream());
 

This line saves the BitmapImage to the library. You may notice that a BitmapImage doesn’t normally have a ToStream method. I think it should so I’ve used an extension method to add it. The extension class doesn’t have anything to do with the Media Library but here it is so you know how it works:

public static class BitmapExtensions
{
    public static Stream ToStream(this BitmapImage bitmap)
    {
        var writeableBitmap = new WriteableBitmap(bitmap);
        var stream = new MemoryStream();
        writeableBitmap.SaveJpeg(stream, bitmap.PixelWidth, bitmap.PixelHeight, 0, 100);
        stream.Position = 0;
        return stream;
    }
}
 

After that code is executed, the image will be accessible in the Media Library. To show this in our sample app you can click the gear icon in the app tray and the new image will be available to be selected using a PhotoChooserTask.

clip_image004[6]

Getting a List of Songs

In the sample app the screen shows a list of the songs that are in the user’s Media Library. The list is a ListBox. A DataTemplate is defined that binds the Text property of two TextBlock’s. One displays the song title and the other displays the artist. Here is what the XAML looks like for the ListBox:

<ListBox
    x:Name="lstSongs"
    SelectionChanged="SongSelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel
                Margin="0,0,0,17"
                Width="432"
                Height="78">
                <TextBlock
                    Text="{Binding Name}"
                    TextWrapping="Wrap"
                    Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                <TextBlock
                    Text="{Binding Artist.Name}"
                    TextWrapping="Wrap"
                    Margin="12,-6,12,0"
                    Style="{StaticResource PhoneTextSubtleStyle}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
 

Setting the ItemsSource to the list of songs is quite simple:

var library = new MediaLibrary();
lstSongs.ItemsSource = library.Songs;
 

What Else Is There?

There are a few other properties off of the MediaLibrary class to take a look at:

Albums – This is similar to the Songs collection but lists albums instead.

Artists – Just like the Albums collection, this collection lists the artists of the songs.

Genres – This collection lists the genres of the songs.

Playlists – This collection lists the playlists that the user has added to their library.

Summary

As you can see, using the Media Library is quite easy. Most of the code in the sample app is written to use the content, not to access it from the library. I talked about how to access the Songs collection and how to save an image to the library. I discussed a few ways to use the library in your own apps. I’m sure there are many other ways to use this content. Have fun and I can’t wait to see your apps.

To download a full Windows Phone project that includes all of the code and concepts from this article, click the Download Code button below.

download

Tomorrow, we will cover globalization/localization in the article, and show you how easy it is to include this in your Windows Phone project.  See you then!

toolsbutton

31 Days of Mango | Day #27: Microphone API

Day27-MicrophoneAPIDay26-BackgroundFileTransfersDay25-BackgroundAgentsDay24-ProfilerToolDay23-ExecutionModel

This article is Day #27 in a series called 31 Days of Mango, and was written by guest author Parag Joshi. Parag can be reached on Twitter at @ilovethexbox.

Introduction

Speech recognition or taking notes is a very common practice depending on your profession or usage. For e.g. it is understood that today’s mobile devices offer some kind of speech recognition and application control, whether it is directions or dialing a number or the other most common usage, playing music.

Note taking is another feature that is useful in recording findings in the field for later reference.

The very first step to all of these applications is to be able to capture the audio via the microphone and process it as needed.

So today we will look at the microphone API provided in Mango and we will put together a very simple sample to get you started.

What is involved?

At the very minimum, we need to record the audio and save it for playback. This gives the user the very basic ability to take notes.

The following key points should be noted:

  1. Microphone class: This is the class provided by the Microsoft.Xna.Framework.Audio namespace that allows us access to the microphone api.
  2. public event EventHandler<EventArgs> BufferReady: This is an event provided when the microphone is ready to release the buffered audio. We need to handle this event and store the audio for playback.
  3. Microphone.Start: As the name suggests, we call this to start recording.
  4. Microphone.Stop: We call this to stop recording. One key point to note here is that calling Microphone.Stop immediately clears out the buffer.

As you will see in the application, we don’t call stop immediately when the user toggles the microphone or clicks the play button. Instead we let the microphone raise the buffer ready event at the selected buffer duration to capture the last bit of audio data before stopping recording.

using Microsoft.Xna.Framework-> As you must have guessed from the microphone namespace, we require a reference to the XNA framework. The microphone API is part of the XNA framework and requires simulating the XNA game loop. If you are not familiar with XNA, XNA is a rich framework provided by Microsoft for game and graphics based applications.

Understanding the sample

Prerequisites: Install the Mango tools from http://create.msdn.com. This should give you Visual Studio Express 2010 and the Windows Phone SDK that you need to develop applications for Windows Phone.

1. Launch Visual Studio and browse to the solution file and open it. The application is built using the Silverlight "Windows Phone Application" template. Run the project and deploy to the emulator. You will see the following screen when the application finishes loading:

clip_image002

2. Screen element:

a. The microphone button is a toggle which starts and stops the microphone.

b. The play button is used to playback the recorded sound.

c. There are three slider controls to adjust the volume, pitch and pan of the sound being played back. These properties can be adjusted only before starting playback.

3. How it works:

a. Touch the microphone to start recording. You can stop recording by touching the microphone again or alternatively touching the play button.

b. Adjust the volume , pitch and pan one by one and test the effect of the change by playing the recorded sound.

Understanding the code

Declarations: Here is a screenshot of the declarations.

clip_image004

We will be using an object of the SoundEffectInstance class to playback the recorded audio. We could also have used a SoundEffect however using the SoundEffectInstance class allows us to track the state (playing or stopped).

The other declaration here is for a MemoryStream object. The microphone buffer is constantly written to a memorystream until playback is desired. At that time,we submit the contents of the memorystream to the SoundEffectInstance object to play.

Initialization:

clip_image006

The key point to note here is the game loop we have created using the DispatcherTimer. This loop is essential to capturing the audio from the microphone.

We set the image for the play icon based on the light or dark theme used in the phone.

At this point we also set up the microphone defaults for our application as follows:

clip_image008

The buffer duration is set to 1/2 second and then we use a method GetSampleSizeInBytes and pass the buffer duration to get the right buffer size. This is important to ensure smooth audio capture.

We wire up the buffer ready event and set the default stopped microphone image.

We are ready to start recording!

Recording Audio:

When the user clicks the microphone button the following code is called:

clip_image010

There are a few things happening here:

1. Microphone is stopped: If the microphone is stopped we need to start it to begin recording. We set the background of the microphone button. Then we reset to MemoryStream to clear out previously recorded audio. We check and stop the recorded sound from playing.

Fairly straightforward steps. At a minimum we need to call Microphone.Start(). The rest of the steps are based on the UI and application design.

2. Microphone is recording: At a minimum we have to stop recording. If you recall the note from above, we cannot call Microphone.Stop immediately as all recorded data has not been flushed to the MemoryStream. So we use boolean varibles to keep track and defer the stop action to DispatchTimer event.

Two things need to happen here. First, we need to let the microphone bufer ready event fire first so we can read the last bit of audio and then we need to trigger playback. We handle it as follows:

clip_image012

In the buffer ready event, we check if recording has been stopped using our boolean variables and then we call Stream.Flush(). This flushes the remaining data to the MemoryStream. Then we stop the microphone.

However we cannot trigger playback in this event. That is handled by the DispatchTimer tick event as follows:

clip_image014

The tick event is called every 33ms. So it will trigger fairly close to the user selecting playback with relatively no indication of a lag. The advantage ofcourse is that we can playback the entire audio rather than letting it get cut off.

We check if it is time to play the recording and whether the stream has been flushed. If so we start a new thread for audio playback. This is an important point to note here.

We are triggering audio playback on a different thread to allow the UI to update. This means any code inside our playback routine that chooses to update UI elements has to do it by calling Dispatch.BeginInvoke as shown below.

Playback:

clip_image016

We create an object of the SoundEffectInstance class by feeding it the captured audio stream, the sample rate of the microphone and the audio channel.

Since we wish to use the sliders to adjust volume, pitch and pan we have to use Dispatcher.BeginInvoke as they are on a different thread.

Finally we call Play.

Summary

So, its fairly simple to create an application to record audio. We can extend this application to save the recorded audio to isolated storage and give it a title chosen by the user. We can add a listview of the recordings from isolated storage and turn this into a note taking application.

The basic steps to record audio are

a) Wire an event to the default microphone to capture the audio.

b) Write the audio to a stream.

c) When the user stops recording, flush the stream and store it or playback.

We can also extend this sample by taking the recorded audio and sending it to a speech translation service and capture commands.

To download a full Windows Phone application that uses all of the code and examples from above, click the Download Code button below.

download

Tomorrow, Jeff Fansler will be covering the Media Library class, and how we can use it to learn more about a user’s music library on their phone.  See you then!

toolsbutton

31 Days of Mango | Day #26: Background File Transfer

Day26-BackgroundFileTransfersDay25-BackgroundAgentsDay24-ProfilerToolDay23-ExecutionModelDay22-AppConnect

This article is Day #26 in a series called 31 Days of Mango, and was written by guest author Gary Johnson.  Gary can be reached on Twitter at @GaryGJohnson.

Yesterday we created a project using a Background Agent, one of the multitasking features new to Windows Phone 7.5. Today we will use Background File Transfer to perform a file download that continues even when our application is not running. We will download a video from Channel 9 and play it when completed.

Getting Started

Launch Visual Studio and create a new project. Under Silverlight for Windows Phone, select Windows Phone Application. Name it “MyFileTransferApp”.

clip_image002

You’ve now created the main application. It will be responsible for:

1) Starting our video download

2) Displaying the status of the download

3) Playing the video once download has completed

Creating the Application

Now it’s time to actually wire everything up. Open MainPage.xaml and add two Buttons for downloading and playing the video. Then, add two TextBlocks for displaying download progress and status.

<StackPanel VerticalAlignment="Center">
    <Button x:Name="downloadButton" Click="downloadButton_Click">Start Download</Button>
    <Button x:Name="playVideoButton" Click="playVideo_Click" IsEnabled="False">Play Video</Button>
    <TextBlock x:Name="progressText" Margin="10"/>
    <TextBlock x:Name="statusText" Margin="10"/>
</StackPanel>
 

I won’t include the entirety of MainPage.xaml.cs here, but it is available in the attached solution. First, we define some instance variables to hold the location of our video to be downloaded, the location where we will save the video, and the current transfer request:

private const String SAVE_LOCATION = "shared/transfers/MyDownloadedVideo.mp4";
private Uri videoDownloadUri = new Uri("http://video.ch9.ms/ch9/02df/0a2774a9-a010-4b9b-b654-9f88014102df/xboxCompanion_med_ch9.mp4&quot;);
private Uri saveLocationUri = new Uri(SAVE_LOCATION, UriKind.RelativeOrAbsolute);
private BackgroundTransferRequest _currentRequest = null;
 

Note that when downloading directly to Isolated Storage, all downloads must go into shared/transfers/. We will be downloading a video from Channel 9 and saving it as “MyDownloadedVideo.mp4”.

When a user clicks “Start Download”, we will create a new BackgroundTransferRequest and tell it what we want to download, and where we want the download to be saved. By default, a download can only be performed when the device is plugged in and has a Wi-Fi connection. We adjust this by setting BackgroundTransferRequest.TransferPreferences to AllowCellularAndBattery. Finally, we add our request to the BackgroundTransferService.

_currentRequest = new BackgroundTransferRequest(videoDownloadUri, saveLocationUri);
_currentRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
BackgroundTransferService.Add(_currentRequest);
 

We also need to be notified of the request status and progress so we can update our UI. We can subscribe to changes by handling the TransferProgressChanged and TransferStatusChanged events:

_currentRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(_currentRequest_TransferProgressChanged);
                _currentRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(_currentRequest_TransferStatusChanged);
 

When we get notified of those events, we can check several properties on our BackgroundTransferRequest to see the current state of the download:

  • BytesRecieved / TotalBytesToRecieve for progress of a download
  • BytesSent / TotalBytesToSend for progress of an upload
  • TransferStatus for the current status of the download (transferring, completed, etc.)
  • TransferError for information about a failed transfer.

Note that whether or not the transfer was successful, TransferStatus will report Completed when finished. Because of this, once TransferStatus reports a Completed status, you should check TransferError to see if an error occurred.

When the transfer is completed, you should remove it from the BackgroundTransferService:

BackgroundTransferService.Remove(_currentRequest);
 

Finally, one of the trickier aspects of implementing a background file transfer is dealing with your application getting closed. When we re-enter the application, we need our status to continue updating, even through _currentRequest is going to be null and our events are no longer wired up. To deal with this, we reset our _currentRequest and wire up the events in OnNavigatedTo:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    foreach (BackgroundTransferRequest request in BackgroundTransferService.Requests)
    {
        _currentRequest = request;
        break;
    }

    InitializeCurrentTransferRequest();
    InitializeTransferRequestEventHandlers();
    RefreshTransferUI();
}
 

While functional, this example is overly simplistic. It is recommended that you also check out the Background File Transfers Overview on MSDN for a more complete reference.

Running the Application

Now that our application is ready to go, deploy it to the device emulator or Windows Phone and run the MyFileTransferApp. Click “Start Download” and you should see download progress reported:

clip_image003

Hit the Start button and leave the application. Wait for a while, and then re-open the application. You should notice that the progress of the download has continued even when the application was not running. Once the status is Complete, you can click “Play Video” to watch the video that was downloaded.

Summary

So, today we created a BackgroundTransferRequest that downloads a video. When making transfer requests of your own, keep in mind what we covered:

  • Start a BackgroundTransferRequest and add it to the BackgroundTransferService to begin a download or upload
  • Save downloads in share/transfers/ when saving to Isolated Storage
  • Handle the BackgroundTransferRequest.TransferProgressChanged and BackgroundTransferRequest.TransferStatusChanged events to be notified of changes in transfer state
  • When BackgroundTransferRequest.TransferStatus is Complete, remember to check BackgroundTransferRequest.TransferError to see if the transfer was successful
  • Handle scenarios where the user leaves and returns to your application

To download a complete Windows Phone project that includes all of the code from this article, click the Download Code button below.

download

Tomorrow, Parag Joshi is back to discuss the Microphone API, and how we can use it to capture audio from a Windows Phone device.  See you then!

toolsbutton

31 Days of Mango | Day #25: Background Agents

Day25-BackgroundAgentsDay24-ProfilerToolDay23-ExecutionModelDay22-AppConnectDay21-Sockets

This article is Day #25 in a series called 31 Days of Mango, and was written by guest author Gary Johnson.  Gary can be reached on Twitter at @GaryGJohnson.

Today we’re going to take a look at one of the multitasking capabilities new to Windows Phone 7.5. The complete multitasking picture is comprised of several new features:

  • Background Agents
  • Background File Transfer
  • Background Audio Playback
  • Scheduled Notifications
  • Fast Application Switching

Here we will focus on Background Agents. While the file transfer and audio playback tasks cover specific scenarios, they do not allow for custom code to be executed. That is where Background Agents come in.

There are two types of Background Agents: Periodic and Resource Intensive. Resource Intensive agents are meant for tasks that will consume a large amount of system resources and come with several limitations for when they can be run. Periodic agents run more frequently and with less restriction, but are meant for tasks that are light on resource consumption. To fully understand the different limitations and benefits of each, refer to the MSDN page.

A periodic task might do something short and simple, such as refresh an RSS feed or update your live tile. A resource intensive task might do something that requires a lot of time and bandwidth, such as syncing or caching large amounts of data from a cloud service.

We are going to make a Periodic Agent that will update your application live tile with the last time the custom task was run.

Getting Started

Launch Visual Studio and create a new project. Under Silverlight for Windows Phone, select Windows Phone Application. Name it “MyAgentApp”.

clip_image002

You’ve now created the main application. It will be responsible for two things:

1) Having a live tile that the Background Agent can update with information

2) Starting and stopping the Background Agent

The Background Agent itself must live in its own special project. Add a new project to your solution, selecting Windows Phone Scheduled Task Agent. Name it MyAgent. This project will contain your custom code that will run in the background and update the live tile.

clip_image004

Finally, and this is important, go to the MyAgentApp project and add a project reference to MyAgent. This will allow you to register your agent from within the application. Also, notice the entry this automatically created in WMAppManifest.xml:

<Tasks>
      <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
      <ExtendedTask Name="BackgroundTask">
        <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="MyAgent" Source="MyAgent" Type="MyAgent.ScheduledAgent" />
      </ExtendedTask>
    </Tasks>
 

Creating the Application

Now it’s time to actually wire everything up. Open MainPage.xaml and add two buttons, one for starting the agent, and the other for stopping the agent:

<StackPanel VerticalAlignment="Center">
        <Button Content="Start Background Agent"
               Click="StartButton_Click"/>
        <Button Content="Stop Background Agent"
               Click="StopButton_Click"/> 
    </StackPanel>
 

 

In MainPage.xaml.cs, wire up the buttons to start and stop the agent:

private const string TASK_NAME = "MyAgent";

private void StartButton_Click(object sender, RoutedEventArgs e)
{
    StartAgent();
}

private void StopButton_Click(object sender, RoutedEventArgs e)
{
    StopAgentIfStarted();
}

private void StartAgent()
{
    StopAgentIfStarted();

    PeriodicTask task = new PeriodicTask(TASK_NAME);
    task.Description = "This is our custom agent for Day 25 – Background Agents";
    ScheduledActionService.Add(task);
#if DEBUG
    // If we’re debugging, attempt to start the task immediately
    ScheduledActionService.LaunchForTest(TASK_NAME, new TimeSpan(0, 0, 1));
#endif
}

private void StopAgentIfStarted()
{
    if (ScheduledActionService.Find(TASK_NAME) != null)
    {
        ScheduledActionService.Remove(TASK_NAME);
    }
}
 

 

Notice that to create our custom agent, we are creating a new PeriodicTask. We then use the name as an identifier when finding and stopping the agent. Notice also that we specified PeriodicTask.Description – this is a required field and will appear in Settings | Background Tasks under the name of our application.

Create the Background Agent

In the MyAgent project, open ScheduledAgent.cs and add the following code:

protected override void OnInvoke(ScheduledTask task)
{
    UpdateAppTile(GetLastUpdatedTimeMessage());
}

private string GetLastUpdatedTimeMessage()
{
    return string.Format("Last Updated: {0}", DateTime.Now);
}

private void UpdateAppTile(string message)
{
    ShellTile appTile = ShellTile.ActiveTiles.First();
    if (appTile != null)
    {
        StandardTileData tileData = new StandardTileData
        {
            BackContent = message
        };

        appTile.Update(tileData);
    }
}
 

ScheduledAgent has one important method to override – OnInvoke. This is where your agent will execute its background task. If your task is complete and you no longer need your agent to run, you can call NotifyComplete() to signal that the task completed successfully or Abort() to signal that you are cancelling your task. To keep the task running at an interval, simply do not call either, which is what we are doing here.

Running the Application

Now that our application is ready to go, deploy it to the device emulator or Windows Phone and run the application. Click the button to start the background agent. Leave the application and find it in your list of applications. Tap and hold on the application and choose “pin to start”. When you view the tile on your start page you should eventually see the application tile flip around, revealing the last time it was updated.

clip_image005

Summary

So, today we created our own custom Background Agent that updates a live tile. When making Background Agents of your own, keep in mind what we covered:

  • Background Agents allow you to execute custom code while your application is not running
  • There are two types of Background Agents – Periodic and Resource Intensive
  • Periodic tasks are for tasks that have low resource consumption, and as a result have fewer restrictions than Resource Intensive tasks
  • Background Agents need their own project, which should be added as a project reference to the application that will start the agent
  • In your agent you need to override OnInvoke()
  • When your task is completed you need to call NotifyComplete() or Abort()

To download a complete Windows Phone project that uses all of the code and concepts from above, click the Download Code button below:

download

Tomorrow we are going to look at another multitasking feature called Background File Transfer that will allow us to download or upload files while our application is not running.  See you then!

toolsbutton

31 Days of Mango | Day #24: Performance Analysis

Day24-ProfilerToolDay23-ExecutionModelDay22-AppConnectDay21-SocketsDay20-Ringtones

This article is Day #24 in a series called 31 Days of Mango, and was written by guest author Chris Koenig.  Chris can be reached on Twitter at @chriskoenig.

Performance is an important aspect of all applications, especially apps that run on resource constrained, network reliant mobile devices. As a user, it is relatively easy to tell when a running application is “slow”; what is not so easy is identifying the cause of the performance problems. Making changes to the source code without understanding the effect on performance can lead to unnecessary refactoring and potentially make the problems worse.

What to do? With the release of Windows Phone “Mango”, we can now easily identify the source of our application’s performance problems – all the way down to the functions that are causing the issues. Enter the Windows Phone Profiler tool. You can use the new Windows Phone Profiler to help identify issues with performance in your application including memory consumption, visual tree complexity, application launch time, and identifying long-running functions.

To run a performance analysis session, open your Windows Phone Project in Visual Studio and select “Start Windows Phone Performance Analysis” from the Debug menu, or press the ALT-F1 shortcut key:

image_thumb

Be sure that you are launching the Windows Phone profiler, and not the .NET profiler, which is also found on the Debug menu, listed as “Start performance analysis (ALT-F2)”.

The first thing you’ll see is a page asking you to select the type of analysis you want to do. Unless you know specifically that there is a memory consumption problem, you should always start with the Execution analysis:

image_thumb1[1]

Clicking the “Launch Application” link will start up your application on either the emulator or the device with all the monitoring code automatically added to your session. Once the application is started, navigate around your application exercising those features of your application that are the most performance-critical or that are going to be most frequently used by your users. As you put your application through its paces, tracing information will be be automatically collected and recorded by Visual Studio for later review.

Once your testing session is complete, switch back over to Visual Studio and click the “Stop Profiling” link:

image_thumb1

At this point, Visual Studio will save all the performance profile data into a .SAP file and add that file to your project. This file will be keyed to your project, as well as the execution date and time of the test (e.g. DatabaseForMango_2011_11_14_17_59_27.sap”. This recording can be reviewed now, or saved for later viewing. The main view of the results is the set of graphs that are provided. These graphs represent a number of different measurements that are all stacked on top of each other to provide a timeline-based view of your applications performance.

image_thumb5

Starting at the top, these graphs show

  • Frame Rate: This shows the recorded frame rate for each frame rendered in the UI. Low numbers here are potential trouble spots that warrant more investigation.
  • CPU Usage %: Shows CPU usage across different parts of the application
    • Green bars represent the UI thread – this is the one to watch as high usage of the UI thread causes the UI to become unresponsive to user input. Any value over 50% is a potential problem area.
    • Blue bars represent the Application threads – this includes and user-created background threads and the composition thread (higher is better, compared to UI thread)
    • Grey bars represent System threads – these are the threads that are NOT part of your application, but represent things like background tasks, etc.
    • White bars represent Idle threads – like the “System Idle Process” shown in Windows Task Manager, this represents the available CPU percentage. A higher number means a more responsive UI.
  • Memory Usage in MB: Watch this if you get more than 90MB anywhere and run the other test – 90MB is the limit for passing marketplace certification.
  • Storyboards: an S is displayed at each frame where a Storyboard is launched.
    • Red represents a CPU-bound storyboard (these are bad as they run on the CPU thread and directly impact UI performance)
    • Purple represents a GPU-bound storyboard (these are good as they’re run on the Compositor thread and do not affect UI performance).
  • Image Loads: An “I” will show up on the frame to indicate where an Image is being loaded into memory.
  • Garbage Collection Events: A “G” will show up to indicate a point at which the Garbage Collector is run.

To see the details of the data that is feeding the graph you simply use the mouse to select a region of the graph containing those frames that you want to drill down into. The lower section, referred to as the Detailed Performance Analysis section, will populate with Warning and Informational messages that highlight areas of concern for the selected frames:

image_thumb3

From this picture, you can see that two specific warnings are called out related to frame rate problems. For example – the first warning in the picture above contains the following information:

Warning: Very low frame rate potentially caused by a high layout cost.
Total layout time (0.35 seconds) is high. Element System.Windows.Controls.ScrollViewer : ScrollViewer took the most time in layout and is contributing to the low frame rate. This could be because CPU-bound animations are causing layout updates. Go to the Performance Warnings menu in the navigation toolbar and select the Frames view. Sort the frames by clicking the CPU Time column header and select the frames with the highest CPU time. From the Frames view, select the Visual Tree option and identify visual System.Windows.Controls.ScrollViewer : ScrollViewer in the tree.

This warning calls out the low frame rate based on how the layout is constructed relative to the ScrollViewer. The suggested action indicates that we should drill into the Performance Warnings menu and select the Frames view. If you look closely at the Detailed Performance section, you’ll see that right next to the Performance Warnings item is a button that controls a pop-up menu containing several choices beneath it into which we can “drill down” for more information. If you choose the “Frames” option, you will see something like this:

image_thumb4

This list of the actual frames selected shows that many of them have a CPU usage well over 50% – in this case there is even one with over 80%! Selecting that frame, and going back to the navigation menu next to the Frames item from before, shows that there are still more levels of detail we can get to for that particular frame. Select each one of the items to get further information about what’s going on with that particular frame. Looking at items such as the Functions option will allow you to see what methods are being called in your application, and will provide links back to your source code for those methods from the application that are being executed. You can also look at the Visual Tree, Element Types and Cache Updates. These error messages, combined with the direct guidance given on where to look for problems and the tool’s ability for you to drill down into the root cases gives you a great viewport into your application to discover potential trouble spots and fix them before submitting to the marketplace for certification.

Now that we’ve seen how the tool works, here are a couple of tips for using it that will help speed you on your way to a speedier application:

  • Start with the Execution Performance tests to see if there are any memory issues, as indicated by the Memory Usage graph. If you discover spots where your application is consuming over 90MB of memory, run a second test focusing specifically on the Memory settings. You’ll normally find that any performance issues can be diagnosed with this first test, so only use the second test when memory concerns warrant it.
  • Don’t forget to test Fast Application Switching, Tombstoning and the corresponding Activation processes – these are all important parts of your application. To force tombstoning in your application when you press the start button, go into the project properties under the Debug tab and check “Tombstone upon deactivation while debugging”. Otherwise, your app will default to FAS.
  • Always performance test on a device – the performance of your laptop will not compare to the performance of your device. This goes back to the old “we’re not shipping this app on your laptop” axiom of testing. The Windows Phone device is much more resource constrained than the typical development workstation, so memory and performance issues will be more likely on the device than on the emulator. Running these tests against the device works the same way as traditional debugging on the device – just change the Deployment Target from “Windows Phone Emulator” to “Windows Phone Device” up in the Standard Visual Studio Toolbar.

Summary

Here are some links to additional resources on Windows Phone Performance Analysis:

Tomorrow, Gary Johnson will be writing about Background Agents, and how we can use this new feature of Windows Phone 7.5 to execute code even when our application isn’t running.  See you then!

toolsbutton

31 Days of Mango | Day #23: Execution Model

Day23-ExecutionModelDay22-AppConnectDay21-SocketsDay20-RingtonesDay19-AddingTiltEffects

This article is Day #23 in a series called 31 Days of Mango, and was written by guest author Samidip Basu.  Samidip can be reached on Twitter at @samidip.

Let’s just agree – our smartphones are pretty smart these days. But all the emails, social integration, games & applications do take a toll on the smartphone’s comparatively tiny processing system & memory, but more importantly battery life. It is thus crucial for any mobile OS & third-party applications to be very responsible in optimizing the use of resources in a smartphone, so as to provide the most fluid, responsive, yet lasting user experience. This is where Execution Models come into play & it becomes important to understand the various states/events during an application’s lifecycle. In this article, we talk about what the Execution Model looks like for Windows Phone & what has changed in the Mango release for consumers/developers.

The Windows Phone Way

As we dance between various parts of the Windows Phone OS & third-party applications all day, the phone takes a well-defined approach to managing the lifecycle of applications from launch to termination. The execution model simply allows only one application to run in the foreground at any time. While we shall see how this is beneficial to the user experience, let me play devil’s advocate & argue for the contrary. However, even if it was possible, can you really envision running multiple applications side-by-side in the foreground in a Windows Phone? Isn’t the screen real estate too limited to try doing that? The focus on one application at the foreground simply makes sense for the phone form factor and engages the user in a chrome/distraction free immersive experience. Where this is more real estate to play with, similar Metro UI operating systems do allow multiple foreground applications to be docked side-by-side, as in Windows 8 snapped views. But I digress J

So, this decision of one application on the foreground does have implications on the lifecycle of an application. Most Windows Phone users are very used to quickly moving between 3rd-party applications & the OS itself through the use of Start/Back buttons, Tiles & Toasts etc. Each Windows Phone application goes through several phases, each exposing events, as we cycle through the application’s time in the foreground. Details follow.

The Application States

In essence, each Windows Phone application cycles through the following states:

  • Running – This is the foreground primetime for any application. The OS & the user give the application all the attention to carry out what it does.
  • Dormant – The moment an application steps out of the foreground, it immediately goes into a Dormant stage. This is a new enhancement in Windows Phone Mango, where the whole application with its state & backstack history is kept intact in memory. The goal here is satisfy the supreme responsiveness of applications on resume, which have just fallen out of the foreground, in case the user wants to return to the application. This is what we call Fast Application Switching (FAS) in Windows Phone Mango.

Want to try it? Well, needless to say, you need a Windows Phone running Mango or the latest Emulator. Jump between several parts of the OS or through multiple 3rd party applications, then hold down the Back button .. and voila! You see something like this, don’t you?

FAS

What you are seeing is the Application backstack, an in-memory footprint of applications that are in Dormant state, ready to spring back to the foreground on your one tap. To the consumer, this is multi-tasking. To you as a developer, this is FAS .. a very quick application resume without you having to do anything! Well except for recompiling your pre-Mango applications using the latest Windows Phone SDK 7.1. This immediately has two effects – your application doesn’t show the old “Resuming …” message if coming back to foreground from Dormant state & you also see the application screenshot in the Application backstack. We shall see some code in a bit.

  • TombstonedNow, as we saw, the Windows Phone runtime keeps a backstack of in-memory Dormant applications that have recently been on the foreground. While the instant resume is great, any smartphone has limited memory availability and the OS might need support to pull off an expensive operation. Guess what happens next .. yep, applications fall off the backstack in Last-In-First-Out mode! In other words, they are tombstoned & considered to be not consuming any system resources beyond that point. The last statement is technically not entirely true, as we shall see in a minute.

So, how does Tombstoning affect an applications lifecycle? Well, if the user has been using your application, and then went on to a few very resource-intensive games, there is a chance that eventually your application might be tombstoned to release some memory back for system consumption. However, the user might decide to traverse the backstack to get back into your application after a while. How should your application behave? Can we remember things the user was up to when he/she left our application?

The answer is yes! We can absolutely provide the user with an experience that might come across as if he/she never really left your application & start from where they left off. To achieve this effect, however, needs us developers to share some responsibility to manage the state of our application throughout its lifecycle. In the code that follows, we shall see how we can hydrate our application state when resuming an application out of Tombstone, to give the end user the impression that the application never actually got killed. The truth is even when an application in Tombstoned, some little data (as a dictionary) about the state of the application and backstack of pages within the application is preserved in memory by the Windows Phone OS.

  • Terminated – An application in this state has absolutely zero memory footprint on the Windows Phone OS. Nothing, including State dictionaries, which we talk about later, is preserved and any subsequent use of the application results in a fresh instance. An application reaches this stage after it has been Tombstoned or the user back-navigated past the first page or there was an unhandled exception killing the application.

Pages & Events

Before we move on to application lifecycle events, let us take a small step back to make sure our fundamentals are right. All Windows Phone Silverlight applications run as a collection of XAML pages that are loaded inside a Phone Application Frame. While the application is in the foreground, the user is free to navigate between pages inside the application. Hitting the phone’s Back button makes the user traverse through a backstack of pages inside an application, until the first page of the application is hit & then next Back key press exits our application. We, as developers, need not do anything to make this happen, as the Windows Phone OS takes care of this automatically during the application’s primetime in the foreground.

But consider this .. a user is typing some content in a text input control on one XAML page, gets distracted & actually moves out of our application to carry out some operation. When he comes back, two things might happen. One, the application could have just been Dormant & springs right back into foreground, retaining the exactly what the user was typing .. there is nothing your application needs to do to support this, except for checking on an API to make sure you application was Dormant. Secondly, your application may have been Tombstoned & now you have a little problem. You need to bring your application back to life & hydrate the state of the XAML page to exactly how the user left it .. this we shall see in code.

So, now that we are talking Page States, it is a good time to talk about two events during a page’s own life span:

  • OnNavigatedTo – This event fires when the page is being brought to the foreground for display. This provides us developers an opportunity to read query strings passed into the page or hydrate the page controls appropriately if coming out of Tombstone.
  • OnNavigatedFrom – This event fires when the user is leaving the present page to go to another page within the application or leaving the application altogether. In either case, this serves as a good checkpoint to save any state information for the current page, in case restoration may be needed in future. We shall see examples in code.

Data & State Dictionaries

Now, let’s take a look at what kind of data we are trying to preserve & hydrate/dehydrate during our application’s Execution Model. In my opinion, application data on Windows Phone is of two types:

  • Settings & Permanent Data – This type of data is the crux of your application and needs to be persisted across application runs/instances. We should waste no time in saving such data straight to Isolated Storage, either as Name/Value pairs or Files/Directories, or in SQL CE if the data is relational.
  • Page & Transient Data ­– This is the expendable, but convenient to save data & is mostly dealt with in memory. This type of data could be anything ranging from user-entered unsaved data on a page or some ViewModel or some temporary data per application lifecycle, fetched from outside. This is the data we need to handle carefully to give the end users an impression that our application is alive & kicking throughout its lifecycle. Now, we have some help. Windows Phone OS exposes a Dictionary to each application & each application page that could be used to store serializable Key-Value pair data. This State dictionary is off of the PhoneApplicationService and should only be used to store transient state data. You should not use this property for excessive storage because there is a limit of 2 MB for each page and 4 MB for the entire application; but as we shall see in code, this is rather helpful in maintaining state during our application’s execution model. And it is these dictionaries that are persisted by the Windows Phone OS even after our application has been tombstoned. If the application is reactivated from Tombstone, this state dictionary will be populated with the data we saved in it during application’s Deactivation. Because this data is present in memory, we can use it to restore state without resource-intensive file operations.

Application Events

Now that we know all the details & the inside workings, let’s just see when we do what during an application’s lifecycle. The PhoneApplicationService raises 4 primary events during an application’s execution model that helps us manage state:

· Launching – This event is raised when a new application instance is created by user actions like launching from application list, or by tapping on Tile/Toast or other means. In this case, we begin with a fresh slate, and not as any continuation of past application lifecycles.

· Deactivated – This event is raised when the users navigates away from our application or a Chooser is launched. This is the best opportunity for us to save the state of the application into the State dictionary for future use in resuming the application. If resumed from Dormant state, this would not be necessary; but absolutely needed if resuming from Tombstone and the Deactivated event is the only chance we shall get to save application-level state.

· Activated – This event is fired when the application is returning to the foreground, either from being Dormant or Tombstoned. Guess what .. a simple API flag called the IsApplicationInstancePreserved off of the event args tells us what state our application is resuming from. If the flag is true, our application has just been Dormant & held in memory; so no action is required and FAS kicks in. If the flag is false, we are returning from Tombstone & would use the state dictionary to restore application state.

· Closing – This event fired when the user traverses through the application’s page backstack & past the first application page. At this point, the application should have exited the foreground & terminated itself after raising an event. No state information is preserved on termination and subsequent launches of the application would result in fresh instances.

As a common theme, heavy resource intensive tasks should be avoided during any of the above application events, since we have a limited amount of time (10 seconds to be precise) that the OS would wait for our methods to finish. For best user experience, some of the expensive operations of maintaining state should be performed on background threads while the application is running.

Want to make sense of all of the above information? Well just take a look at the overall Execution Model diagram for Windows Phone, best described by an MSDN article:

Execution Model

[Courtesy MSDN]

Demo Application

We have been all-talk so far, haven’t we? Let’s see some code! We’re going to build a simple Windows Phone application that highlights state management across the application’s lifecycle. The entire built application is available for download at the end of the article; just make sure you have Windows Phone SDK 7.1, grab the bits & hit F5!

So, let’s begin. File -> New & we accept the most basic default template for an application with one XAML page only, that being MainPage.xaml/cs. We are going to open up the XAML page & drop some demo controls for our sake. The end state is something like this (click to enlarge):

XAML Page

Here’s the goal .. we are going to split up the controls to manage states of various types of data, as described below:

  • App Setting – This is an example of an application level setting that has to be persisted across application instances. Most common example would be a user setting for your application.
  • App Transient Data – This set of controls will simulate application level data that is only applicable per application instance, but may be usable in multiple XAML pages throughout the application. Best such example would be some web service data that an application fetches every time it runs afresh.
  • Page Transient Data – This set of controls stands for page specific control data that we possibly do not want to lose if the user steps out of our application & comes back to it through application backstack.

We’re going to handle each type of data separately. So, let’s start with the App.xaml.cs – the place to handle global application logic/data. Let’s add some custom properties/initializers, along with a little code in the Constructor:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class App : Application
    {
        public PhoneApplicationFrame RootFrame { get; private set; }

        public bool AppSetting { get; set; }
        public string AppData { get; set; }

        public static new App Current
        {
            get { return Application.Current as App; }
        }

        // Constructor.
        public App()
        {
            // All other initialization code ..
            AppData = string.Empty;

            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                AppSetting = (bool)IsolatedStorageSettings.ApplicationSettings["AppSetting"];
            }
        }
    }
}
 

 

Next, we’re going to add some code to application’s lifecycle event handlers. Notice the use of the IsApplicationInstancePreserved flag to decide whether we are coming out of Dormant/Tombstoned state in the application’s Activated event handler. Now, I didn’t have a good reason to add any special code to the application’s Launching/Closing event handlers; but you are free to if your application needs any such code. Also, notice the use of the State dictionary off the PhoneApplicationService:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class App : Application
    {
        public PhoneApplicationFrame RootFrame { get; private set; }

        public bool AppSetting { get; set; }
        public string AppData { get; set; }

        public static new App Current
        {
            get { return Application.Current as App; }
        }

        // Constructor.
        public App()
        {
            // All other initialization code ..
            AppData = string.Empty;

            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                AppSetting = (bool)IsolatedStorageSettings.ApplicationSettings["AppSetting"];
            }
        }

        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
            if (e.IsApplicationInstancePreserved)
            {
                // Returning from Dormancy.
                // Do nothing.
            }
            else
            {
                // Returning from Tombstone.
                if (PhoneApplicationService.Current.State.ContainsKey("AppData"))
                {
                    AppData = PhoneApplicationService.Current.State["AppData"].ToString();
                }
            }
        }

        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
            PhoneApplicationService.Current.State["AppData"] = AppData;
        }

        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Other auto-generated code here ..
    }
}
 

 

Now, back in our MainPage.xaml’s code-behind, let’s add event handlers for the page’s loading event & the click of the button to fetch some data (which we totally fake), as well as the application setting checkbox’s state being changed. Notice how we hang on to the fetched data at the application level and also how we immediately save application/user settings in the phone’s Isolated Storage:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor.
        public MainPage()
        {
            InitializeComponent();
        }

        private void chkAppSetting_Tap(object sender, GestureEventArgs e)
        {
            // Store App Setting changes immediately in Isolated Storage for persistence.
            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("AppSetting");
            }

            if ((bool)this.chkAppSetting.IsChecked)
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", true);
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", false);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.txtAppData.Text = "This is some sample data ..";

            // As if we are caching the data.
            App.Current.AppData = this.txtAppData.Text;
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.chkAppSetting.IsChecked = App.Current.AppSetting;
        }
    }
}
 

 

Now, let’s add the all-important page navigation events. This is where we get to control how we hydrate/dehydrate transient data as the XAML page comes to the foreground & moves out of it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor.
        public MainPage()
        {
            InitializeComponent();
        }

        private void chkAppSetting_Tap(object sender, GestureEventArgs e)
        {
            // Store App Setting changes immediately in Isolated Storage for persistence.
            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("AppSetting");
            }

            if ((bool)this.chkAppSetting.IsChecked)
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", true);
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", false);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Fake data fetch..
            this.txtAppData.Text = "This is some sample data ..";

            // As if we are caching the data.
            App.Current.AppData = this.txtAppData.Text;
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            // Load user setting from Isolated Storage.
            this.chkAppSetting.IsChecked = App.Current.AppSetting;
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // Load in App Data, if available.
            if (App.Current.AppData != null && App.Current.AppData != string.Empty)
            {
                this.txtAppData.Text = App.Current.AppData;
            }

            // Load any Page State, if available.
            if (PhoneApplicationService.Current.State.ContainsKey("PageData"))
            {
                this.txtPageData.Text = PhoneApplicationService.Current.State["PageData"].ToString();
            }
            if (PhoneApplicationService.Current.State.ContainsKey("PageSetting"))
            {
                this.chkPageSetting.IsChecked = (bool)PhoneApplicationService.Current.State["PageSetting"];
            }
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            // Clear past state, if any.
            if (PhoneApplicationService.Current.State.ContainsKey("PageData"))
            {
                PhoneApplicationService.Current.State.Remove("PageData");
            }

            if (PhoneApplicationService.Current.State.ContainsKey("PageSetting"))
            {
                PhoneApplicationService.Current.State.Remove("PageSetting");
            }

            // Save off Page state.
            PhoneApplicationService.Current.State["PageData"] = this.txtPageData.Text;
            PhoneApplicationService.Current.State["PageSetting"] = this.chkPageSetting.IsChecked;
        }
    }
}
 

That’s it! We have now added enough code so that the different types of data/state are managed across the lifecycle of the application, each in a different way as appropriate. Go ahead & give it a spin. Start the application, make setting changes, go somewhere else & come back, or exit & run fresh instance of the application. Data & state information should be preserved and wiped as expected. A typical run with settings turned on looks something like this:

App and Page State

Now, you might notice one thing on both the emulator or if deployed to an actual phone. As we cycle through the application, step out & then return to it in the Windows Phone Mango runtime, it is hard to predict when our application would actually be tombstoned. Most times, if deactivated, the application simply sits in Dormant state & comes right back to life. So, although we have code to hydrate settings when coming back from Tombstone, there is not definite way to test it.

Worry not! There is a simple debug setting that is going to forcibly tombstone your application the moment it deactivates. So, even if the application can stay Dormant, this setting, shown below, forces it to be tombstoned. This obviously helps our testing.

Tombstone Setting

Summary

Adding breakpoints to various event handlers and seeing when they fire during an application’s lifecycle, is a great way to understand the Execution Model. So, what are you waiting for? Go ahead and make full use of the Fast-Application-Switching and hydrate/dehydrate your application/page state correctly throughout the lifecycle of the application.

Result – Happy users, and ultimately happier you!  Adios!

To download a complete Windows Phone project that includes all of the concepts covered in this article, click the Download Code button below.

download

Tomorrow, Chris Koenig is going to talk about another great tool available to us in Visual Studio 2010, the Silverlight Performance Analysis Tool.  See you then!

toolsbutton