Using PowerShell to automate the build process of your Windows Phone app

Tools, Windows Phone 5 Comments »

Another day another occasion to share a tip which comes with the development of my todo-list app 2Day. This time, I share a small PowerShell script I use in order to build the application. Of course the script will not work out of the box for you but it could be useful if you’re thinking about automating the generation of your application.

Background: managing multiple versions

Since release 1.5.0 there are two versions of 2Day: the lite version (free) and the standard version (paid). I switch from one configuration to another using two Build Configurations. When I want to build the Lite version I build using the Release Lite configuration while for the standard version I build in Release. The difference between the two is a conditional symbol.

2Day-Configurations

I also have a WP7 and a WP8. So for each official release, I must produce 4 XAPs:

  • WP7 Lite
  • WP7 Full
  • WP8 Lite
  • WP8 Full

This is the reason why I was thinking about automating this stuff !

PowerShell script

The script itself is very straightforward: I use MSBuild to build the Visual Studio Solution File (*.sln) using the 2 configurations I described earlier. Once a build is complete I move the generated XAPs to an output folder. As I said this script will NOT work out of the box for your but it could be used as an example. Here is the code:

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# usage is ./ScripName -version 1.5.0
param([string]$version = "version")
 
$solution = "2Day.sln"
$msbuild = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
# get the location of the script
$rootDir = [System.Io.Path]::GetDirectoryName($MyInvocation.MyCommand.Path)
# build the location of the sln file. In my case this is under /Branches/WindowsPhone/versionunmber/
$baseDir = $rootDir + "\Branches\WindowsPhone\" + $version + "\"
# and the ouput is in a Build folder
$outputFolder = $rootDir + "\Build\"
 
# if the output folder exists, delete it
if ([System.IO.Directory]::Exists($outputFolder))
{
 [System.IO.Directory]::Delete($outputFolder, 1)
 [System.IO.Directory]::CreateDirectory($outputFolder) | Out-Null
}
else
{
 [System.IO.Directory]::CreateDirectory($outputFolder)| Out-Null
}
 
Write-Host "Building 2Day version: " $version
Write-Host "Solution is at: "  $baseDir$solution
 
# make sure our working directory is correct
cd $baseDir
 
$configurations = "Release", "Release Lite"
foreach($configuration in $configurations)
{
	# prepare build command line
	$options = "/noconsolelogger /m /p:Configuration=""" + $configuration + """ /p:Platform=""Any CPU"""
 
	# prepare output path
	$releasePath1 = $baseDir + "2Day.App.WP7\bin\" + $configuration + "\_2DayWP7.xap"
	$outFile1 = "2Day_" + $version + "_WP7_" + $configuration.Replace(" ", "_") + ".xap"
	$releasePath2 = $baseDir + "2Day.App.WP8\bin\" + $configuration + "\_2DayWP8.xap"
	$outFile2 = "2Day_" + $version + "_WP8_" + $configuration.Replace(" ", "_") + ".xap"
 
	# clean
	Write-Host Perform cleaning...	
	$clean = $msbuild + " " + $solution + " " + $options + " /t:Clean"
	Invoke-Expression $clean | Out-Null
 
	# build
	Write-Host "Building with configuration"$configuration"..."
	$build = $msbuild + " " + $solution + " " + $options + " /t:Build"
	Invoke-Expression $build | Out-Null
 
	# move the files that were built to the output folder
	$out1 = $outputFolder + $outFile1;
	$out2 = $outputFolder + $outFile2;
	[System.IO.File]::Copy($releasePath1, $out1)
	[System.IO.File]::Copy($releasePath2, $out2)
 
	Write-Host "Output: " $out1 $out2
}
 
cd $rootDir
Write-Host "Done"

A Reactive Extension (Rx) use case in a Windows Phone app

Rx, Tools, Windows Phone 5 Comments »

While working on my todo-list application 2Day, I encountered a situation where Rx came to the rescue. Rx (Reactive Extension) is a framework which has been available for a couple of years now. It is possible to use it on the phone very easily. In this blog post, I share a piece of code which use Rx to implement a specific feature in 2Day.

2Day’s users have requested a search feature. The idea is simple: give the user a new page where he can type some text which then filters his tasks. Here is the feature in action in 2Day:

2Day - global search

Even though it seems very basic, I wanted to add an extra feature: perform the search a couple of milliseconds after the user actually stops typing. This prevents the search result to blink while the user types. It turns out it’s very easy to implement this using Rx which is dedicated to manipulate stream of observable items. Here is the code:

?View Code CSHARP
1
2
3
4
5
6
7
8
var seq = Observable
    .FromEventPattern<TextChangedEventArgs>(this.textbox, "TextChanged")
    .Throttle(TimeSpan.FromMilliseconds(500))
    .ObserveOnDispatcher()
    .Subscribe(e =>
    {
        this.viewmodel.SearchText = this.textbox.Text;
    });

The first step is to create the observable sequence using the FromEventPattern method which can turn an event into an observable stream. Then the Throttle method allows to “calm down” the stream, by requiring the specified amount of time to be spent before sending the item in the output stream.

This can be shown using the following diagram:

RxExampleThrottle

If the user presses quickly the letters “p”, “a”, “i” and “r” we will start the search only after the specified amount of time and not for each new letter. Notice that the subscribe method does not do a lot of things: it only sets a property on the ViewModel layer which actually performs the search.

Here is a simple yet useful use case for Rx. It’s very nice to have the library available out of the box on the phone. Hope it helps :-)

Tips and tricks when using voice recognition in a Windows Phone 8 app

Windows Phone 3 Comments »

While working (again) on 2Day, I encountered small issues with voice recognition. The next version of 2Day will bring support for both speech recognition (use your voice to set the title of a task) and voice commands (speak to your phone to perform operations, for example: “2Day add a reminder tomorrow at 9PM”).

While developing those new features I used two distinct API for voice recognition:

The first one provides no UI while the second one includes a default GUI which is uniform across apps and utilities:

Listenning

Issue 1: stop music playback automatically

In 2Day, I use the SpeechRecognizerUI when the user must confirm a choice while seeing what is visible on the screen. When using those APIs I faced a first problem which is music playback is not stopped automatically during voice recognition. It turns out a simple API can be used for this:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void PauseMusicPlayback()
{
    this.wasPlayingMusic = MediaPlayer.State == MediaState.Playing;
    if (this.wasPlayingMusic)
    {
        FrameworkDispatcher.Update();
        MediaPlayer.Pause();
        FrameworkDispatcher.Update();
    }            
}
 
public void ResumeMusicPlayback()
{
    if (this.wasPlayingMusic)
    {
        // it looks like FrameworkDispatcher.Update() is needed when using the MediaPlayer
        FrameworkDispatcher.Update();
        MediaPlayer.Resume();
        FrameworkDispatcher.Update();
    }
}

With a simple boolean field, I can save before starting voice recognition if I will have to resume music playback.

Issue 2: use default sound with SpeechRecognizer

When using the SpeechRecognizer class (the one without the default UI) I faced another problems: start/end of voice recognition is not surrounded by the small system sound that indicates that the recognition has started/ended. I thought the easiest way to get this sound as a WAV file on my machine was to use an Audio Capturing tool such as Audacity.

Long story short: that was a bad idea. And it turns out… The original sound files are installed with the SDK !

If you browse the following directory C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Sounds you will be able to get the 2 WAV files ! And use them in your app (you can see my older blog post about how to play WAV file in a Silverlight Windows Phone app).

SoundFiles

Hope it helps :-)

Wanted: Windows Phone / Windows 8 developers for 2Day !

Events 1 Comment »

Almost one year ago, I decided to create a simple but efficient todo list application for Windows Phone 7. In April 2012, I released 2Day, a fast and fluid todo list application. Today, while I’m busy preparing a new version which leverage new stuff available in Windows Phone 8 I also have big plans for Windows 8.

And now, that just too much for a single man. This is why, I’m now actively looking for a couple of developers who would like to join me in the 2Day development team!

If you:

  • Have development experience in C# and XAML (WPF, Silverlight, Windows Phone or Windows 8)
  • Want to work on an interesting app full of innovative features
  • Speak English or French
You will enjoy:
  • the latest cool technologies available
  • working in a international context (2Day is localized in 5 languages)
  • engaging directly with 2Day’s users through the UserVoice website
  • organize you work with the team
  • build the Windows 8 app from the ground up

Note: I’m not offering full time job here. 2Day is a personal development project I’m doing on my free time ;-)

Please drop me an email using the Contact form or via Twitter. I Hope to get in touch with you soon.

Hello World, WinRT !

CodeProject, Windows Phone, WinRT 4 Comments »

Now that the mysterious WP7 app I was working on for the last few months is done (at least v1.0!) and is in the certification pipeline, I finally have some time to start playing with WinRT.

Of course, the first thing I’m playing with is the port of this WP7 app to WinRT. In this post, I’m sharing the aspects I discovered this afternoon while trying to port one of the project from Windows Phone to WinRT. Let’s be clear my goal was just to see what it’s look like to port the code, I wasn’t able of course to port the WP7 app to WinRT in an afternoon…

Tooling

The development environment for Windows 8 is currently:

  • Windows 8 Consumer Preview
  • Visual Studio 11 Beta
  • Blend for Visual Studio Beta

Because I wanted to have the Windows Phone environment too on this machine, I also installed:

The WP7 app currently uses various libraries (all of them are described in this blog post), today I just downloaded the Windows 8 version of MVVM Light (thanks Laurent).

Hello, World

As a developer, one of the first thing we try when we target a new platform is to display some kind of message on the screen. So I first tried the famous MessageBox.Show() but I quickly realized the API has changed… If you want to display a message box, you must use the MessageDialog class:

?View Code CSHARP
1
2
3
MessageDialog dialog = new MessageDialog("Content", "Title");
dialog.ShowAsync();
// execution continues here immediately after showing the dialog

As you can see, displaying the dialog is actually an asynchronous operation. If we want to perform an action when the dialog closed, we must await that call:

?View Code CSHARP
1
2
3
MessageDialog dialog = new MessageDialog("Content", "Title");
await dialog.ShowAsync();
// execution continues here when the dialog closes

If you want to display additional buttons, you can add commands to the dialog:

?View Code CSHARP
1
2
3
MessageDialog dialog = new MessageDialog("Content", "Title");
dialog.Commands.Add(new UICommand { Label = "test" });
IUICommand result = await dialog.ShowAsync();

Namespace changes

Many namespace has changed between Windows Phone and WinRT, you can use pre-processor directives like the following

?View Code CSHARP
1
2
3
4
5
#if WINDOWS_PHONE
using System.Windows.Data;
#else
using Windows.UI.Xaml.Data;
#endif

IValueConverter

Another thing I noticed is the fact that the IValueConverter interface has changed (notice the last parameter…)

WPF/Silverlight/WindowsPhone version (documentation):

?View Code CSHARP
1
2
3
4
5
public interface IValueConverter
{
    object Convert(object value, Type targetType, object parameter, CultureInfo culture);
    object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
}

WinRT version (documentation):

?View Code CSHARP
1
2
3
4
5
public interface IValueConverter
{
    object Convert(object value, Type targetType, object parameter, string language);
    object ConvertBack(object value, Type targetType, object parameter, string language);
}

Storage

The storage story in WinRT can be summarized by the following:

  • file system access is heavily restricted (this was already the case for Silverlight and Windows Phone)
  • most storage API are asynchronous

Here is an example taken from the WinRT documentation:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// write a file
async void WriteTimestamp()
{
    StorageFolder localFolder = ApplicationData.Current.LocalFolder;
 
    StorageFile sampleFile = await localFolder.CreateFileAsync("dataFile.txt", CreationCollisionOption.OpenIfExists);
    await FileIO.WriteTextAsync(sampleFile, DateTime.Now.ToString());
}
 
// read a file
async Task ReadTimestamp()
{
    try
    {
        StorageFolder localFolder = ApplicationData.Current.LocalFolder;
 
        StorageFile sampleFile = await localFolder.GetFileAsync("dataFile.txt");
        String timestamp = await FileIO.ReadTextAsync(sampleFile);
        // Data is contained in timestamp
    }
    catch (Exception)
    {
        // Timestamp not found
    }
}

Resources

The WP7 app contains several resource files (.resx). The resources are available in the XAML (using a binding to a static resource) and in C# using the static types that are automatically generated with the resx file. Well, it looks like those static types do not exist anymore in WinRT (also, the extension of the resource file has changed to .resw).

The resources can now be accessed using the ResourceLoader type:

?View Code CSHARP
1
2
res = new ResourceLoader("PrototypeZero/AppResources");
string value = res.GetString("StringKey");

Conclusion

I think .Net developers should not be afraid by WinRT. If you already start playing with C# Async you will be familiar with the new asynchronous API. As far as I’ve gone with the comparison I think we can reasonably imagine having a good code base shared between WinRT and Windows Phone. I can safely continue to use the XAML knowledge I got about 5 years ago on WinRT :-)

Of course there are many other things we can compare between WinRT and Windows Phone… This first post is just the beginning :-)

Windows Phone Tango (7.1.1)

Events, Windows Phone 1 Comment »

Day 1 of Mobile World Congress has been the occasion for Microsoft to introduce officially the Windows Phone Tango, or Windows Phone 7.1.1

A CTP of the 7.1.1 SDK is now available. This CTP does NOT comes with a go-live license, it basically means you will NOT be able to publish apps to the marketplace with it.

“The Windows Phone SDK 7.1.1 Update provides additional functionality to the existing Windows Phone SDK 7.1 software to enable mobile developers to better target applications for 256MB Windows Phone devices. This update includes an updated 512MB emulator, as well as a new 256MB emulator image, and Intellisense support to communicate device targeting preferences. Once installed, the WP SDK 7.1.1 update allows you to decide which emulator you would like to deploy your app to.”

It is important to note that generic background agents will NOT be available on devices will only 256MB of memory… Read the What’s new in Windows Phone SDK 7.1.1 for more details. At this point it does not look like Microsoft has communicate any other details related to the OS itself (new features or bug fixes…).

As I said in my last post, the next big step now is Windows 8 Consumer Preview on wednesday…

Oh, and by the way, I case you missed it, Skype for Windows Phone 7 is now available in beta. Here is the QR code:

Track memory usage of your Windows Phone 7.1 app in real time

Windows Phone 1 Comment »

Update January 17th: I just found out that Peter Torr released more than a year ago a similar helper class which is very nice. You can check out his solution here.

Memory usage is an important aspect, especially on mobile device. If you want to publish an app on the Windows Phone marketplace you must satisfy the Technical Certification Requirements: “5.2.5 Memory Consumption: An application must not exceed 90 MB of RAM usage, except on devices that have more than 256 MB of memory.”

In this post, I’m sharing a technique to track the memory usage of a WP7 app in real tile in every single page of the app. By adding only one line of code in your existing app, you’ll be able to display memory usage in all your pages (without any changes):

Download source code and example

How to integrate the component in your existing app?

  1. import the MemoryWatcher class in your existing project
  2. in the InitializePhoneApplication method, add a new line after the creation of the RootFrame:
?View Code CSHARP
1
2
3
4
5
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
// Add the following line !
new MemoryWatcher(RootFrame) { IsDisplayed = true };

How it works?

During its initialization, the MemoryWatcher control will set an event handler to have a callback whenever the user navigates to a new page. When the new page is loaded, it checks if it can dynamically insert the MemoryWatcher control. This is done by checking the root UI element of the page and inserting the watcher control in it. Here is the full code of the MemoryWatcher class:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Threading;
 
using Microsoft.Phone.Controls;
using Microsoft.Phone.Info;
 
namespace MemoryWatcherDemo
{
    public class MemoryWatcher : ContentControl
    {
        private readonly DispatcherTimer timer;
        private readonly PhoneApplicationFrame frame;
        private const float ByteToMega = 1024 * 1024;
 
        public bool IsDisplayed { get; set; }
 
        public MemoryWatcher(PhoneApplicationFrame frame)
        {
            if (frame == null)
                throw new ArgumentNullException("frame");
 
            this.frame = frame;
            this.frame.Navigated += new NavigatedEventHandler(this.OnFrameNavigated);
            this.frame.Navigating += new NavigatingCancelEventHandler(this.OnFrameNavigating);
 
            this.timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
            this.timer.Tick += new EventHandler(this.OnTimerTick);
 
            // setup some basic properties to ensure the content will be visible
            this.Foreground = new SolidColorBrush(Colors.Red);
            this.VerticalContentAlignment = VerticalAlignment.Center;
            this.HorizontalContentAlignment = HorizontalAlignment.Center;
            this.Margin = new Thickness(0, -35, 0, 0);
        }
 
        private void OnFrameNavigated(object sender, NavigationEventArgs e)
        {
            if (!this.IsDisplayed)
                return;
 
            var page = this.frame.Content as PhoneApplicationPage;
            if (page != null)
            {
                Panel host = page.Content as Panel;
                if (host != null && !host.Children.Any(c => c is MemoryWatcher))
                {
                    this.timer.Start();
                    host.Children.Add(this);
                }
            }
        }
 
        private void OnFrameNavigating(object sender, NavigatingCancelEventArgs navigatingCancelEventArgs)
        {
            var page = this.frame.Content as PhoneApplicationPage;
            if (page != null)
            {
                Panel host = page.Content as Panel;
                if (host != null && host.Children.Contains(this))
                {
                    this.timer.Stop();
                    host.Children.Remove(this);
                }
            }
        }
 
        private void OnTimerTick(object sender, EventArgs e)
        {
            try
            {
                string currentMemory = (DeviceStatus.ApplicationCurrentMemoryUsage / ByteToMega).ToString("#.00");
                string peakMemory = (DeviceStatus.ApplicationPeakMemoryUsage / ByteToMega).ToString("#.00");
 
                this.Content = string.Format("Current: {0}MB Peak: {1}MB", currentMemory, peakMemory);
            }
            catch (Exception)
            {
                this.timer.Stop();
            }
        }
    }
}

Note:

  • The MemoryWatcher is looking for a Panel type in order to add itself to the list of children in the page. You might want to modify and improve this portion in order to better fit your needs.
  • The attached project targets Windows Phone 7.1, if you want to use the code in a 7.0 version, you should change the way the memory values are read (see this article for more details)

Enjoy the code and start tracking memory leaks :-)

Download source code and example

 

Meet me during the Microsoft Days in Lyon next Wednesday !

Build, Events, Silverlight, Windows 8, Windows Phone, WPF No Comments »

Next Wednesday (November 9th), I’ll be at the Microsoft Days 11 as a member of the Ask The Expert team. I’ll be playing with the Samsung Slate I got at //BUILD/, discussing WPF, Silverlight, Windows Phone 7 and Windows 8.

Don’t hesitate to stop by and say hi if you’re coming to this event !

MVVM Framework explorer updated

Silverlight, Windows Phone, WPF 1 Comment »

I just updated my MVVM frameworks explorer Silverlight application. You can find the updated application here.

Here is the top 5 of MVVM frameworks supporting WPF, Silverlight and Windows Phone 7:

  1. MVVM Light (61k downloads)
  2. nRoute (19k downloads)
  3. Caliburn Micro (18k downloads)
  4. Simple MVVM toolkit (5k downloads)
  5. Catel (5k downloads)

[WP7] Using the camera in the emulator

Windows Phone 21 Comments »

In the very first release of the SDK for Windows Phone 7 development, it was not possible to use the camera in the emulator. The latest version of the SDK fixes this problem.

Windows Phone 7 SDK comes with a set of Task (in the Microsoft.Phone.Tasks namespace). A task can be launched from your application in order to perform some work. Currently available tasks are:

In order to launch a task from your application, all you need to do is to instantiate the associated type and call the Show() method.

Here is a sample code which launchs the StartCameraTask and then gets the capture images in order to use it in a standard Silverlight Image control:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// launch the camera capture when the user touch the screen
this.MouseLeftButtonUp += (s, e) => new CameraCaptureTask().Show();
 
// this static event is raised when a task completes its job
ChooserListener.ChooserCompleted += (s, e) =>
{
    var taskEventArgs = (TaskEventArgs<PhotoResult>)e;
    var photoStream = taskEventArgs.Result.ChosenPhoto;
 
    var bitmapImage = new BitmapImage();
    bitmapImage.SetSource(photoStream);
 
    this.image.Source = bitmapImage;
};

The image is just a standard Silverlight Image control:

1
<Image x:Name="image"/>

The emulator while the task is running:

The captured image (shown once the task has completed):

If you haven’t download the tool already, go ahead and grab them ! Everything is available for free in a single download at http://developer.windowsphone.com/windows-phone-7-series/.

Hope this helps :-)

Note: even though the StartCameraTask is now working, this is not yet the case for all the tasks…

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in