DCSIMG
May 2011 - Posts - Alex Golesh's Blog About Silverlight Development

May 2011 - Posts

Windows Phone Mango–What’s New? (“Profiler” - Part 9 of 8)

This post is a “missing part” of series about new features in Windows Phone Mango Smile

New and very important feature of Windows Phone “Mango” Developer Tools is the profiler. The profiler enables the developers of Silverlight applications (currently only Silverlight scenarios are supported) to sense important heartbeats of the application and collect information about application behavior at runtime.

To measure the performance or the application, navigate to Debug menu option and select Start Windows Phone Performance Analysis:

clip_image001

Visual Studio provides the developer with configuration setting screen which enables him to define some profiling settings, like drawing details, depth of stack frames in each collection, data collection frequency and others:

clip_image002

Finally, when “Launch Application” button pressed, the application starts on selected target (Emulator or Device) and developer should execute the regular application flow (actions). Visual Studio collects the data in the background:

clip_image003

Profiling stopped by clicking “Stop Profiling” button; the application terminates and Visual Studio transfers the measured data into the developers’ PC for analyzing and graphical representation:

clip_image004

Once the data is ready it is presented to developer along with some warnings and recommendations based on application behavior:

clip_image006

Based on selection, and in addition to those warnings, the developer presented with detailed graphs of Draw Frame Rate, CPU and memory usage, running storyboard, images load and garbage collects. In addition, the lower part enables the developer to browse through various presentations of sampled data:

clip_image007

For example check which Visual elements were presented in each single frame and which visual types builds those elements:

clip_image008

hhich active storyboards running at specified period of time:

clip_image010

how log takes to render the application’s Visual Tree:

clip_image012

and many others.

Stay tuned for more posts to come.

Alex

Windows Phone Mango–What’s New? (“Push Notifications & Tiles” - Part 8 of 8)

Mango introduces some changes in Push Notifications mechanism which enables the developers to create more attractive scenarios.

First feature I’ll show in this post is a secondary tiles for application. Before Mango, every application could have only one pinned tile on the main screen which could be updated using Push Notification mechanism (I blogged about it quite some time ago here and here).

Mango release enables to have additional tiles which can be pinned and removed from application code! How about having something like this:

imageimage

All the tiles (beside IE9) on main screen are related to sample I’m going to show here… And they are flipping randomly! Clicking on the tile will take us directly to the person’s mood page:

image

The UI of the app will be very simple – only a bunch of checkboxes to create/remove secondary tiles:

image

Checking the checkbox will add corresponding secondary tile to the main screen; unchecking the checkbox will remove it.

Let’s see how to achieve it. First, my application uses PushNotification channel created (or found) when application loaded:

//Check push channel status and subscribe to the events
pushChannel = HttpNotificationChannel.Find("MoodPushChannel");
if (null == pushChannel)
{
    pushChannel = new HttpNotificationChannel("MoodPushChannel");

    SubscribeToChannelEvents();

    pushChannel.Open();

    pushChannel.BindToShellTile();
}
else
{
    SubscribeToChannelEvents();

    uri = pushChannel.ChannelUri;

    if (!pushChannel.IsShellToastBound)
        pushChannel.BindToShellToast();

    // Uri for diagnostic -- to use from server side
    if (null != uri)
        Debug.WriteLine(uri.ToString());
    else
        Debug.WriteLine("PushChannel.ChannelUri is null");
}

In my sample I’ll use the debug output to pickup the channel URI and use it for sending notifications from cloud-based website:

image

In case of this simple application I don’t really need RAW Notifications and TOAST notifications, so I’ll subscribing only for ChannelUriUpdates and ErrorOccured events:

private void SubscribeToChannelEvents()
{
    pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
    pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
}

void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
    uri = e.ChannelUri;

    if (!pushChannel.IsShellToastBound)
        pushChannel.BindToShellToast();

    Dispatcher.BeginInvoke(() =>
    {
        Debug.WriteLine(uri.ToString());
    });
}

void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
    Dispatcher.BeginInvoke(() =>
        MessageBox.Show(String.Format("A push notification {0} error occurred.  {1} ({2}) {3}",
            e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData)));
}

Now let’s see how to create a secondary tile (one of checkbox’s event handlers function):

private void chkAlex_CheckedUnchecked(object sender, RoutedEventArgs e)
{
    if (!StillInitializing)
    {
        if (chkAlex.IsChecked.Value)
        {
            StandardTileData initialData = CreateTile("Alex");
            ShellTile.Create(new Uri("/MoodInfo.xaml?Name=Alex", UriKind.Relative), initialData);

        }
        else
        {
            //TODO...
        }
    }
}

And helper method:

private static StandardTileData CreateTile(string Name)
{
    StandardTileData initialData = new StandardTileData
    {
        BackgroundImage = new Uri("images/DEFAULT.png", UriKind.Relative),
        Title = Name,
        BackContent = "No updates yet",
        BackTitle = "Mood",
    };
    return initialData;
}

Let’s see what’s new in those methods. First – StandardTileData. It is a new class which defines the behavior of the secondary tile. It enables to define titles, contents and images for both sides of the tile. It also enables setting the count property to front face of the tile.

Note: If back property was not set, the tile will not flip.

Next – creating the tile itself: ShellTile.Create accepts the URI parameter which will serve two purposes: the ID of the tile and the URI within the application to navigate if the tile clicked.

Those parameters also affect the tile notification format sent to the application through Push Notification Server:

Content-Type: text/xml
X-WindowsPhone-Target: token

<?xmlversion="1.0"encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
  <wp:Tile Id="THE URL">
    <wp:BackgroundImage><background image="" path=""></wp:BackgroundImage>
    <wp:Count><count></wp:Count>
    <wp:Title><title></wp:Title>
    <wp:BackTitle><back side="" title=""></wp:BackTitle>
    <wp:BackContent><back side="" content=""></wp:BackContent>
    <wp:BackBackgroundImage><back side="" background="" image="" path=""></wp:BackBackgroundImage>
  </wp:Tile>
</wp:Notification>

Bold parts are new for Mango.

When the tile arrives to the phone it will be identified by ID (which also serves as relative URI in the app) and will use provided images from application’s content.

Note: if secondary tile already removed (not found) nothing happens, no error thrown.

Note #2: the application doesn’t need to have primary tile on the main screen in order to make secondary tile to work.

Since it is not possible to create two tiles with the same ID, we need to manage the tiles from the application. For this matters ShellTile class provides the collection of ActiveTiles which represent all pinned tiles of the application (including the main tile if pinned by user).

The sample checks the pinned stated for secondary tiles and sets the corresponding checkbox state:

//Check for pinned secondary tiles and update UI
ShellTile toFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("Alex"));
if (null != toFind)
    chkAlex.IsChecked = true;

Same done when the tile need to be removed when unchecking the ckeckbox (after the “//TODO…” in “chkAlex_CheckedUnchecked” function):

ShellTile toFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("Alex"));
toFind.Delete();

This way tiles added and removed from the main screen. See the video of working application below:

Working application

Last feature I want to talk about is known as “deep toast”. It enables to send relative URI to the application and navigate to specific page when TOAST notification clicked by user. In addition I’ll show how to send a local push notification message.

First – the change you have to make for your server side logic to sent deep toast message via push notification server:

Content-Type: text/xml
X-WindowsPhone-Target: toast

<?xmlversion="1.0"encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
  <wp:Toast>
    <wp:Text1><string></wp:Text1>
    <wp:Text2><string></wp:Text2>
    <wp:Param><THE URL=""></wp:Param>
  </wp:Toast>
</wp:Notification>

Bold line is new for Mango.

In order to create local deep toast I’ll use Background Agent (see part 5 in case you missed it) which will notify the user about mood change.

In the agent class I’ve created string arrays with mood/names:

string[] Names = { "Alex", "Nicole", "Medeya", "Bru" };
string[] Moods = { "anger", "burn", "confused", "cool", "cry", "fire", "grimace", "love",
            "miao", "prettiness", "question", "shout", "slobber", "smile", "spook",
            "startle", "surprise", "sweat", "thirst", "vomit"};
Random rnd = new Random();

When agent awakes I’m creating new ShellToast instance:

protected override void OnInvoke(ScheduledTask task)
{
    if (!isChanceled)
    {
        int nameNum = rnd.Next(Names.Length);
        int moodNum = rnd.Next(Moods.Length);

        ShellToast toast = new ShellToast();
        toast.Title = "Mood Change!";
        toast.Content = Names[nameNum] + " changed mood";
        toast.NavigationUri = new Uri("/MoodInfo.xaml?Name=" + Names[nameNum] + "&Mood=" + Moods[moodNum], UriKind.Relative);
        toast.Show();
    }
    NotifyComplete();
}

The  NavigationUri points to the existing page in my application. Clicking on it takes user into specific page in the app.

image

Note: Due to bug in beta the deep toast feature is not working and will navigate always to the MainPage.xaml regardless to the URI provided. This feature should be fixed after beta.

The sample used in this post hosted here.

This is it… Will be happy to answer more questions.

Stay tuned for more Mango posts to come Smile

Alex

Windows Phone Mango–What’s New? (“Silverlight/XNA Interoperability” - Part 7 of 8)

Windows Phone RTM didn’t allowed to mix Silverlight and XNA content. Mango enables the scenarios where Silverlight content can be rendered along with XNA content. In the sample presented in this post we will build 2-pager Silverlight application with pure Silverlight page (1st page) and mixed 3D XNA & Silverlight page (2nd page).

Final application looks like the following:

imageimage

In order to ease on the developers, after installing Mango developer tools, Visual Studio provides us with two templates – one in Silverlight for Windows Phone area and one in XNA Game Studio 4.0 area:

image

and

image

The templates are almost identical. The first one (from Silverlight section) has some basic texture moving on-screen while second has minimum required to run XNA.

Both solutions has some plumbing in App in order to properly initialize XNA’s ContentManager, FrameworkDispatcher, etc. If you familiar with XNA development you probably know, that the main class in XNA game derives from Game class (part of Microsoft.Xna.Framework namespace). This class takes care of all XNA stuff initialization. In case of hybrid applications, like one we have here, the Silverlight’s application class have to take care about proper initializations.

Review create App.xaml.cs file – it implements IServiceProvider interface (which pure Silverlight applications usually doesn’t), and has XNA application init region with ContentManager and GameTimer initialization:

#region XNA application initialization

// Performs initialization of the XNA types required for the application.
private void InitializeXnaApplication()
{
    // Create the ContentManager so the application can load precompiled assets
    Content = new ContentManager(this, "Content");

    // Create a GameTimer to pump the XNA FrameworkDispatcher
    GameTimer frameworkDispatcherTimer = new GameTimer();
    frameworkDispatcherTimer.FrameAction += FrameworkDispatcherFrameAction;
    frameworkDispatcherTimer.Start();
}

// An event handler that pumps the FrameworkDispatcher each frame.
// FrameworkDispatcher is required for a lot of the XNA events and
// for certain functionality such as SoundEffect playback.
private void FrameworkDispatcherFrameAction(object sender, EventArgs e)
{
    FrameworkDispatcher.Update();
}

#endregion

Note: you don’t have to write this code if you are using a visual studio template; if you need to add some XNA parts to your existing Silverlight application you have to write this in order to use XNA.

Let’s see the “GamePage.xaml” create by Visual Studio - first thing you probably mention there is:

<!--No XAML content as the page is rendered entirely with XNA-->

Ok, let’s understand what is it and why.

Silverlight/XNA interoperability is based on Silverlight’s implementation of XNA class – GraphicsDeviceManager; in Silverlight hybrid apps it called SharedGraphicsDeviceManager. It allows to “switch” rendering mode from Silverlight’s retained graphics mode to XNA’s immediate graphics. Unfortunately  SharedGraphicsDeviceManager’s switch affects all the screen area, which means there are no way to mix between XNA and Silverlight rendering engine on the same screen. Let’s deal with this limitation later on.

My sample uses relatively simple 3D model of Alien Spaceship (could be found in XNA Creators Club Samples). The rendering procedure is exactly the same as we (at least I do) used to do in XNA.

Note: I created simple class to take care on all 3D rendering named XnaModelWrapper.cs which can be found in attached sources. This post is focused on hybrid apps and not on XNA – to understand how 3D rendering works in XNA please refer to XNA documentation and tutorials.

Our GamePage class uses GameTimer to emulate XNA’s game loop and subscribes to Update and Draw events. Those events match (by name and meaning) to the corresponding events in regular XNA games:

// Create a timer for this page
timer = new GameTimer();
timer.UpdateInterval = TimeSpan.FromTicks(333333);
timer.Update += new EventHandler<GameTimerEventArgs>(timer_Update);
timer.Draw += new EventHandler<GameTimerEventArgs>(timer_Draw);

In addition I want to provide some level of interactivity to my 3D model and for this sample I preferred to use XNA’s TouchPanel class. It provides me with built-in gestures recognition (which Silverlight doesn’t):

//Initialize gestures support - Pinch for Zoom and horizontal drag for rotate
TouchPanel.EnabledGestures = GestureType.FreeDrag | GestureType.Pinch | GestureType.PinchComplete;

Now, every 33ms the GameTimer will fire Update event and I’ll handle it as follows:

void timer_Update(object sender, GameTimerEventArgs e)
{
    HandleInput();

    float yaw = MathHelper.Pi + MathHelper.PiOver2 + xRotation / 100;
    float pitch = yRotation / 100;
    model.Rotation = modelMetadata.World * Matrix.CreateFromYawPitchRoll(yaw, pitch, 0);
    model.View = modelMetadata.ViewMatrix;
    model.IsTextureEnabled = true;
    model.IsPerPixelLightingEnabled = true;
    model.Projection = Matrix.CreatePerspectiveFieldOfView(
        MathHelper.ToRadians(cameraFOV) / modelMetadata.FieldOfViewDivisor,
        modelMetadata.AspectRatio,
        modelMetadata.NearPlaneDistance,
        modelMetadata.FarPlaneDistance);
}

The takes care of handling touch input first and the does some calculations to rotate 3D model.

Note: To better understand this code please refer to XNA 3D drawing tutorials

Handle input takes care of gestures reported to the application (according to initialized gestures above):

private void HandleInput()
{
    while (TouchPanel.IsGestureAvailable)
    {
        GestureSample gestureSample = TouchPanel.ReadGesture();
        switch (gestureSample.GestureType)
        {
            case GestureType.FreeDrag:
                xRotation += gestureSample.Delta.X;
                yRotation -= gestureSample.Delta.Y;
                break;

            case GestureType.Pinch:
                float gestureValue = 0;
                float minFOV = 80;
                float maxFOV = 20;
                float gestureLengthToZoomScale = 10;

                Vector2 gestureDiff = gestureSample.Position - gestureSample.Position2;
                gestureValue = gestureDiff.Length() / gestureLengthToZoomScale;

                if (null != prevLength) // Skip the first pinch event
                    cameraFOV -= gestureValue - prevLength.Value;

                cameraFOV = MathHelper.Clamp(cameraFOV, maxFOV, minFOV);

                prevLength = gestureValue;
                break;

            case GestureType.PinchComplete:
                prevLength = null;
                break;

            default:
                break;
        }
    }
}

Pay attention, that I can handle the gesture and not spend my time writing the gesture recognition (or use 3rd party gesture recognition libraries).

After gestures recognized and changes in my model calculated let’s see the Draw event handler:

void timer_Draw(object sender, GameTimerEventArgs e)
{
    SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(background, Vector2.Zero, Color.White);
    spriteBatch.End();

    // Set render states.
    SharedGraphicsDeviceManager.Current.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
    SharedGraphicsDeviceManager.Current.GraphicsDevice.BlendState = BlendState.Opaque;
    SharedGraphicsDeviceManager.Current.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
    SharedGraphicsDeviceManager.Current.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

    // Draw the model
    model.Draw();

    // TODO
    ...
}

This code uses SpriteBatch instance to render 2D graphics (background texture), prepares the GraphicsDevice for 3D rendering and calls for 3D model’s Draw method. The approach is 100% compatible to XNA (beside the graphics device manager class name – in XNA it called GraphicsDeviceManager). This way we achieving the XNA (2D and 3D) content rendering in Silverlight application’s page.

But what about the Silverlight? It is well know, that XNA has no built-in controls - what about mixing some Silverlight controls & XNA?

Let’s change our GamePage.xaml a little bit:

<Grid x:Name="LayoutRoot" Margin="12">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}" 
        Foreground="White"
        Text="{Binding ModelName}" Grid.Row="0"
        VerticalAlignment="Top" HorizontalAlignment="Left"/>
    <TextBlock FontSize="{StaticResource PhoneFontSizeLarge}" 
        Foreground="White"
        Text="{Binding ModelDesc}" Grid.Row="1"
        VerticalAlignment="Top" HorizontalAlignment="Left"/>
    <Button Content="About" x:Name="btnAbout" Click="btnAbout_Click" Grid.Row="2"
        HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
</Grid>

The UI is very simple, yet it has interactive element and databinding. The button_Click event handler is super simple:

private void btnAbout_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello from Silverlight/XNA hybrid application!");
}

Just by adding this XMAL on page it will not show itself. This is a side effect of SharedGraphicsDeviceManager switch – the Silverlight rendering engine is not working, thus nothing rendered:

image

I marked (red rectangle) the are with a button… Clicking inside at the place where the button should be will reveal the “hidden gem” – button still works:

image

This means, that Silverlight is fully functional but just not rendered. To render Silverlight on XNA driving surface we need to use UIElementRenderer – new class in Microsoft.Xna.Framework.Graphics namespace. It responsible of creating XNA’s Texture2D object from Silverlight’s UIElement. This means, that any part of our Silverlight interface could be rendered into XNA texture and used into XNA composition (like we did with a background). TThis means, that we could “paint” real 3D models with Silverlight UI!

Let’s see how to initialize this UIElementRenderer class. It should be initialized with width and height of texture to produce, then best place to initialize it if at Silverlight’s LayoutUpdated event (after all the controls has all the styles applied):

void GamePage_LayoutUpdated(object sender, EventArgs e)
{
    if (uiRenderer == null || LayoutRoot.ActualWidth > 0 && LayoutRoot.ActualHeight > 0)
        uiRenderer = new UIElementRenderer(LayoutRoot, (int)LayoutRoot.ActualWidth, (int)LayoutRoot.ActualHeight);
}

In this sample I’m initializing it from page LayoutRoot element and want to create an image to span over whole screen.

At the Draw event handler I’m replacing the “//TODO…” comment with actual rending command:

// Update the Silverlight UI
uiRenderer.Render();

// Draw the sprite
spriteBatch.Begin();
spriteBatch.Draw(uiRenderer.Texture, Vector2.Zero, Color.White);
spriteBatch.End();

Note, that XNA will render the 2D/3D elements at the order they appears in Draw method. Thus if you want to render part of the screen on upper layer send it to rendering last (like in case I did with Silverlight-rendered texture). Result is expected:

image

and the button is also fully functional (see the pressed state in marked red rectangle):

image

Note (Updated): There is one limitation of the SL/XNA interop - the popup controls are not supported. This means, that controls like Silverlight Toolkit's AutoComplete and list picker do not work in interop mode.

The source used for this post hosted here.

Stay tuned to part 8 – “Push Notification & Tiles”

Alex

Windows Phone Mango–What’s New? (“Fast Application Switch (FAS)” - Part 6 of 8)

The Windows Phone RTM operating system had only one active application and when application were sent to the background the state was serialized and kept in the application’s isolated storage. This process called tombstoning and application in such state called tombstoned. When user return to the tombstoned application, he would have to wait a while as the application deserialized its state and recovered and we as developers had to take care about saving the application’s state and resuming it.

With Mango that is no longer the case: there is only one active (foreground) application, but once an application is sent to the background the operating system keeps its image alive in memory for as long as possible without impairing the performance of the currently active application. This new state of the application called dormant. When user reactivate the dormant application, the experience would be virtually instantaneous as restoring the application’s in-memory image is a fast operation. In case the dormant application’s memory need to be released to ensure active application performance doesn’t hurt, Mango will tombstone the dormant application and user will have to wait to get back to the application as it was in RTM. This new mechanism is called Fast Application Switching (FAS).

This (short) post shows how to be aware of the manner in which your application was restored after being deactivated. When application is activated, ActivatedEventArgs has new property IsApplicationInstancePreserved which indicates the latest state of resumed application. If IsApplicationInstancePreserved is true this means, that all application memory is intact and virtually nothing should be done in such case. If IsApplicationInstancePreserved is false then we need to take care of “old-styled” tombstoning resume:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    // Ensure that application state is restored appropriately
    if (!e.IsApplicationInstancePreserved)
    {
        WasTombstoned = true;

        //Your code to resume from tombstoning
        ...
    }
    else
    {
        WasTombstoned = false;
    }
}

That’s almost it. The default behavior of the Mango application lifecycle manager is to preserve application images in memory as long as possible and the tombstoning process will occur automatically by phone’s operation system when it really needed. But how to check/debug resuming from tombstoning this process with emulator when it has only one application running?

The new version of developer tools allow us to force an application to forego FAS in favor of tombstoning. To force tombstoning, open project’s properties and navigate to the “Debug” tab:

image

Ticking the checkbox that says “Tombstone upon deactivation while debugging” will force your application consistently perform tombstoning upon deactivation while the debugger is attached. Clear the checkbox to have the application use FAS again.

Stay tuned to part 7 – Silverlight & XNA interoperability

Alex

Windows Phone Mango–What’s New? (“Background Agents” - Part 5 of 8)

One of most requested and discussed features of Mango release is “multitasking”. In Mango the multitasking term has slightly different meaning than standard (PC) multitasking. Multitasking for Mango phones means ability to execute the code while application in not active and play audio started by the application in a background. This is achieved by Background Agents. In addition to them Mango also introduces APIs to download and upload files while application is in the background and add Reminders and Alarm to grab user attention.

This post will show how to use those features. During the post I’ll show how to build sample application which uses those features. The application’s UI is very simple:

image

Let’s start from background agents. The Background Agent are class libraries which “manifested” with application and capable of performing periodic tasks (or resource intensive task). To help starting with agents creation Visual Studio provides number of templates:

image

The Task Scheduler Agent is a “classical” background agent for running custom periodic task. Audio Streaming Agent enables background audio scenarios and Audio Streaming Agent enables creating the live audio streaming scenarios which requires custom MediaStreamSource implementation.

Note: The audio scenarios will not be covered in this post.

Added background scheduler agent project has only one class which derives from ScheduledTaskAgent class. By default it overrides two base member functions: OnInvoke and OnCancel.

  • OnInvoke called when phone invokes periodic task (or resource intensive task).
  • OnCancel invoked when agent request is getting canceled.

Background agent is a part of the application and as such it can access all resources available to the application. In this sample the background agent will update file in application’s IsolatedStorage with current DateTime timestamp. Let’s see the implementation details:

public class TaskScheduler : ScheduledTaskAgent
{
    bool isCancelled;

    protected override void OnInvoke(ScheduledTask task)
    {
        //TODO: Add code to perform your task in background
        if (isCancelled)
        {
            NotifyComplete();
            return;
        }

        using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
        {
            //Simulate the process running here..
            byte[] data = System.Text.Encoding.UTF8.GetBytes(DateTime.Now.ToString());

            using (IsolatedStorageFileStream file = iso.OpenFile("data.dat", System.IO.FileMode.OpenOrCreate))
            {
                file.Write(data, 0, data.Length);
                file.Close();
            }
            NotifyComplete();
        }
    }

    protected override void OnCancel()
    {
        base.OnCancel();

        //TODO: This Task is cancelled, do necessary clean up 
        isCancelled = true;
    }
}

The code is very simple. In order to make this class library as application’s background agent we need to add a reference to it from the main application. It will add a corresponding reference also in WMAppManifest.xml:

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

From now on the class library is ready to serve as our application’s background agent. After deploying the application to he Windows Phone Emulator (or device) and navigating to Settings/Applications/background services you will find that our application has background service:

imageimage

and you can turn off background services to any of your applications.

Now let’s get back to the main app and wire the code for enabling/disabling running the background agent:

private void btnStartStopBgTask_Click(object sender, RoutedEventArgs e)
{
    if (!isBackgroundTaskEnebaled)
    {
        PeriodicTask periodicTask = new PeriodicTask("TheWorker");
        periodicTask.Description = "The worker task";
        periodicTask.ExpirationTime = DateTime.Now.AddDays(1);

        ScheduledActionService.Add(periodicTask);
        btnStartStopBgTask.Content = "Stop Background Task";
        isBackgroundTaskEnebaled = true;
    }
    else
    {
        ScheduledActionService.Remove("TheWorker");
        btnStartStopBgTask.Content = "Start Background Task";
        isBackgroundTaskEnebaled = false;
    }
}

This code snippet created a new PeriodicTask named “TheWorker” and scheduled it to run for 1 day. Removing the task is easy – all you need is just the name.

Note, that description is displayed at system background tasks page so give a meaningful names.

At any time you can query the task status by executing Find function:

ScheduledAction scheduledAction = ScheduledActionService.Find("TheWorker");
if (null != scheduledAction)
    if (scheduledAction.IsEnabled)
    {
        //Task is running, do your logic...
    }
    else
    {
        //Task is not running, do your logic...
    }

Next, let’s deal with reminders and alarms. Reminders are popups which be displayed above any active application (even when the phone screen is locked) much like reminder of upcoming meeting:

image

Let’s see how to add one:

private void btnAddReminder_Click(object sender, RoutedEventArgs e)
{
    Reminder r = new Reminder("important");
    r.Title = "Important!";
    r.Content = "Please get back to the application";
    r.BeginTime = DateTime.Now.AddSeconds(20);
    r.NavigationUri = new Uri("/MainPage.xaml?From=REMINDER", UriKind.Relative);

    ScheduledActionService.Add(r);
}

Clicking on reminder will navigate into the application and will use the provided URI (deep linking):

image

Note “REMINDED” added to the button caption when identified that application navigated from the reminder.

The Alarm is pretty similar to the Reminder; it will enable to use any application’s sound as alarm sound (or will use system alarm sound if not provided) but will not have an option to deep link into the application:

private void btnAddAlarm_Click(object sender, RoutedEventArgs e)
{
    Alarm a = new Alarm("theAlarm");
    a.RecurrenceType = RecurrenceInterval.Daily;
    a.Content = "ALARM! Get back to the application";
    a.BeginTime = DateTime.Now.AddSeconds(10);
    a.ExpirationTime = DateTime.Now.AddSeconds(20);
    a.Sound = new Uri("/Sounds/sound.wav", UriKind.Relative);

    ScheduledActionService.Add(a);
}

Receiving the alarm:

image

Last very exciting feature is a Background File Transfer. It enables to transfer files (both directions – upload and download) even when application is not active or tombstoned. Once application activated all the information from corresponding background transfers (events) will be delivered to the app. Let’s download big video file (~30Mb) using background transfer.

void StartDownload()
{
    btr = new BackgroundTransferRequest(remoteVideoUri, localDownloadUri);
    btr.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
    BackgroundTransferService.Add(btr);
    btr.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(btr_TransferProgressChanged);
    btr.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(btr_TransferStatusChanged);
}

The event handlers allow to track the progress status. In our case TransfeProgressChanged event handler will add the progress percentage to the Background Download button:

void btr_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
{
    double progress = e.Request.BytesReceived * 100 / e.Request.TotalBytesToReceive;
    btnBackgroundDownload.Content = "Background Download (" + progress + "%)";
}

and TransferStatusChanged event handler will deal with finished request removal and also will set the downloaded file as a source to MediaElement on the page:

void btr_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
    if (btr.TransferStatus == TransferStatus.Completed)
    {
        btr.TransferProgressChanged -= btr_TransferProgressChanged;
        btr.TransferStatusChanged -= btr_TransferStatusChanged;
        BackgroundTransferService.Remove(btr);

        Dispatcher.BeginInvoke(delegate
        {
            try
            {
                using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    var file = isf.OpenFile(btr.DownloadLocation.ToString(),
                            FileMode.Open, FileAccess.Read);
                    mediaElement.SetSource(file);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ooops, can't load file. " + Environment.NewLine + ex.Message);
            }
        });
    }
}

Working sample:

image

First a few notes:

  • Big files will use WiFi by default to download , like marketplace applications does. Also in some cases big files will be downloaded only when device is connected to power source. In order to override this default behavior change the TransferPreferneces property of BackgroundTransferRequest instance.
    • btr.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
       
  • When download finished it is up to the application to remove the unneeded request from the queue
    • var temp = BackgroundTransferService.Requests.FirstOrDefault();
      if (temp != null)
          BackgroundTransferService.Remove(temp);
      
      
  • The application limited to 5 requests in the BackgroundTransferService queue and need to manage their requests. If application adds more than 5 requests the BackgroundTransferService.Add() command will throw an exception.

See the video of working sample:

Background File Transfer, Alarms & Reminders working sample

 

The sample app  used for this post hosted here.

 

Stay tuned to the part 6 – “Fast Application Switch”.

Alex

Windows Phone Mango–What’s New? (“Camera” - Part 4 of 8)

All Windows Phone 7 devices equipped with camera. The minimum required camera resolution is 5 Mega pixels. For developers accession camera information enables many scenarios like image recognition, video chatting, augmented reality and others. From the beginning, Windows Phone 7 RTM devices supported camera usage scenario via launchers and choosers. Phone shell API provided the developer with CameraCaptureTask which could be used to take a picture and use it in the application. This scenario based on phone’s operation system camera interface and not covered in this post. In this post I’ll cover live camera input.

To use live input from phone’s camera we need to initialize an instance of PhotoCamera class from Microsoft.Devices namespace. Also, to use the camera in your applications define ID_CAP_ISV_CAMERA capability in WMAppManifest.xml:

<Capability Name="ID_CAP_ISV_CAMERA"/>

PhotoCamera class represents the basic camera functionality for a Windows Phone still camera application and enables the developer to configure the camera with resolution, flash and focus settings. Note, that developing camera-enabled application requires the physical device. The Windows Phone Emulator supports camera APIs but doesn’t provide neither hardware button emulation, neither camera visual feedback. The emulator shows white rectangle with small black rectangle travelling around:

image

To use PhotoCamera object it must be assigned as a source to some drawing surface. In our sample we are using VideoBrush object to draw paint with live camera feed. The main surface of our application is covered by Rectangle object with Fill property assigned to the VideoBrush:

<Rectangle x:Name="rectPreview" Width="780" Height="460" Margin="10">
    <Rectangle.Fill>
        <VideoBrush x:Name="previewVideo"/>
    </Rectangle.Fill>
</Rectangle>

In next code snippet we will initialize the PhotoCamera object and assign it as a source to the VideoBrush named previewVideo (this is done in OnNavigatedTo event handler):

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    photoCamera = new PhotoCamera();
    photoCamera.Initialized += new EventHandler<CameraOperationCompletedEventArgs>(photoCamera_Initialized);

    previewVideo.SetSource(photoCamera);

    base.OnNavigatedTo(e);
}

PhotoCamera class take some time to initialize, thus most of the functionality will be available only at Initialized event we subscribed at previous code snippet. The event handler function will take care of rest initializations procedures there:

void photoCamera_Initialized(object sender, CameraOperationCompletedEventArgs e)
{
    if (photoCamera.IsFlashModeSupported(FlashMode.Auto))
        photoCamera.FlashMode = FlashMode.Auto;
    //Select the lowest available resolution
    photoCamera.Resolution = photoCamera.AvailableResolutions.ElementAt(0);
    //Match the preview resolution to the camera resolution
    photoCamera.PreviewBufferResolution = photoCamera.AvailableResolutions.ElementAt(0);
    photoCamera.AutoFocusCompleted += new EventHandler<CameraOperationCompletedEventArgs>(photoCamera_AutoFocusCompleted);
    photoCamera.ButtonFullPress += new EventHandler(photoCamera_ButtonFullPress);
    photoCamera.ButtonHalfPress += new EventHandler(photoCamera_ButtonHalfPress);
    photoCamera.ButtonRelease += new EventHandler(photoCamera_ButtonRelease);
    photoCamera.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(photoCamera_CaptureCompleted);
    photoCamera.CaptureImageAvailable += new EventHandler<ContentReadyEventArgs>(photoCamera_CaptureImageAvailable);

}

This code snippet sets the flash to work automatically, and desired capture resolution. Usually the camera supports more than one resolution. The higher resolution means more pixels packed into the final picture, but also means the bigger resulting file. Our sample will process the live video feed, thus higher resolution also means more pixels need to be processed each frame. To minimize the number of processed pixels and final image size, the code sets first available camera resolution. The PhotoCamera object holds the AvailableResolutions which depends on physical camera component installed. The AvailableResolutions is a collection of CaptureResolution objects. This collection sorted such way, that lower resolutions are at the beginning of the list and higher resolutions are at the end of the list.

Now let’s understand when those events fired:

Event When Fired
AutoFocusCompleted Fired when auto-focus sequence completed
ButtonFullPress Fired when the hardware shutter button receives a full press
ButtonHalfPress Fired when the hardware shutter button receives a half press
ButtonRelease Fired when the hardware shutter button is released
CaptureCompeted Fired when the capture sequence is complete
CaptureImageAvailable Fired when the capture sequence is complete and an image is available

Let’s see how those events are used in our sample. When user press the hardware button half-way down we want to start the auto-focus sequence:

void photoCamera_ButtonHalfPress(object sender, EventArgs e)
{
    photoCamera.Focus();
}

When auto-focus completes and AutoFocusCompleted event fired our sample will show image at the central part of the screen much like regular point-and-shot cameras do:

image

void photoCamera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        imgFocus.Visibility = Visibility.Visible;
    });
}

If user press the hardware buttons fully, the ButtonFullPress event fires and our sample begins image capturing sequence:

void photoCamera_ButtonFullPress(object sender, EventArgs e)
{
    photoCamera.CaptureImage();
}

CaptureImage function starts the asynchronous capturing process. When the capturing process is over, the CaptureCompleted and CaptureImageAvailable events fired. At the CaptureCompleted event handler the sample hides the auto-focus indicator:

void photoCamera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        imgFocus.Visibility = Visibility.Collapsed;
    });
}

When CaptureImageAvailable, the sample saves the captured image into phone’s media library:

void photoCamera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
{
    MediaLibrary mediaLibrary = new MediaLibrary();
    string fileName = string.Format("{0:yyyy-MM-dd-HH-mm-ss}.jpg", DateTime.Now);
    mediaLibrary.SavePicture(fileName, e.ImageStream);
}

The event arguments have the captured image as Stream. Our sample will use XNA’s MediaLibrary class to save the picture. To use it add reference to the Microsoft.Xna.Framework assembly and the following using statement:

using Microsoft.Xna.Framework.Media;

Last, but not least if user releases the hardware button before taking a picture (pressing it full way down), the ButtonRelease event fired. Our sample cancels auto-focus sequence and hides the auto-focus indicator if it already shown:

void photoCamera_ButtonRelease(object sender, EventArgs e)
{
    photoCamera.CancelFocus();

    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        imgFocus.Visibility = Visibility.Collapsed;
    });
}

When leaving the page doesn’t forget to unsubscribe form PhotoCamera events and release the object Smile

In addition to using various camera events, it is possible to receive raw bits from camera to process this data live. The PhotoCamera class provides number of functions to copy current viewfinder frame into array for further processing. The viewfinder frame can be copied as ARGB, YUV or YCrCb pixel data. In our sample we are using ARGB buffer to create the negative image effect. A negative image is a total inversion of a positive image, in which light areas appear dark and vice versa. A negative color image is additionally color reversed, with red areas appearing cyan, greens appearing magenta and blues appearing yellow.

The negative effect created by each color channel value from its maximum value (255 in case of ARGB). The pixel processing done as shown at the following code snippet:

int[] pixelData = new int[photoCamera.PreviewBufferResolution.Width * photoCamera.PreviewBufferResolution.Height];
photoCamera.GetPreviewBufferArgb32(pixelData);

int[] target = new int[pixelData.Length];

for (int i = 0; i < pixelData.Length; i++)
{
    target[i] = Negate(pixelData[i]);
}

This this code snippet we are creating array big enough to accommodate the viewfinder’s date and executes GetPreviewBufferArgb32 function to fill the array. The resulting target array used to initialize an instance of WriteableBitmap and present the effect on screen:

//Copy to WriteableBitmap
target.CopyTo(previewWriteableBitmap.Pixels, 0);

previewWriteableBitmap.Invalidate();

The resulting application will show negative live image preview on phone’s screen. The sample hosted here.

Stay tuned to the part 5 – “Background Agents”.

Alex

Windows Phone Mango–What’s New? (“New Sensors & Tooling Enhancements” - Part 3 of 8)

Windows Phone devices are modern devices. As such, they usually have few sensors such as built-in accelerometer, A-GPS, light sensor, magnetometer, etc. Windows Phone minimum hardware spec requires that all Windows Phone will have at least 4 of them – A-GPS, Accelerometer, Compass and Light sensors. While accelerometer and A-GPS were available for developers with first version of Windows Phone, there are some new sensors which were added with Mango. The hardware market is not standing still, thus we could see much advanced sensors coming out on the modern phone models. Some of those sensors (like gyro for example) were added to Mango API. The table below provides quick compare between RTM and Mango sensors support:

Sensor Windows Phone RTM Windows Phone Mango
Accelerometer Yes Yes
Microphone Yes Yes
A-GPS Yes Yes
Camera Yes Yes
Compass No Optional
Gyro No Optional
Motion No Optional
FM Radio Yes Yes

In some case, even when the sensor hardware component installed on the device it doesn’t mean that is have the managed (.NET) API to access it (for example light sensor).

Mango tools provide better developers support while developing sensors-enables application. In previous release developing accelerometer-enabled or A-GPS-enabled (location-aware) applications required real developer-unlocked phone device or some community solution to emulate sensors input. With Mango release this support provided by Windows Phone Emulator. To emulate accelerometer or location readings open “Additional Tools” windows of emulator:

image

The opened “Addition Tools” window enables accelerometer and location changes emulation. To simulate the accelerometer data, move the pink “ball” with you mouse:

image

The Location tab enables not only to send current location to the Windows Phone Emulator, but also to record the geographical point and send them at given time interval to emulate the device movement:

image

One important note here: while the Windows Phone Emulator provides you a way to simulate the accelerometer and GPS location data, it is advised to check your application also in real device, since real sensors data is subject to environmental influence, network availability, magnetic fields, etc. Always check you application on the real device to see how it behaves under real-world conditions.

Now let’s get back to the sensors. I will cover the changes (or actually additions) to he Camera in next post and focus to new sensors in this post.

All sensor classes in Mango derive from single base class, SensorBase<T>, which makes developer life really easy. All the sensors will be initialized and operated the same way. Only the events and readings data vary between different sensors.

Let’s see common parts of sensors interface:

Base Class Member Info
CurrentValue Property, contains current value of the sensor
IsDataValid Property, contains the validity of the sensor’s data
CurrentValueChanged Event, occurs when new data arrives from the sensor
TimeBetweenUpdates Property, gets or sets the preferred time between CurrentValueChanged events
Start Function, starts acquisition of data from the sensor
Stop Function, stops acquisition of data from the sensor
Dispose Function, releases the managed and unmanaged resources used by the sensor

In general, the pattern to work with the sensor should be as the following:

1. The sensor variable defined at the class level and available for all functions in the class (page).

//Class level variable
Motion motion;

2. Activate the sensor at the latest possible time. Usually OnNavigatedTo event handler is good place for it:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    if (Motion.IsSupported)
    {
        motion = new Motion();
        //Subscribe to sensor-specific events
        motion.Calibrate += new EventHandler<CalibrationEventArgs>(motion_Calibrate);
        motion.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<MotionReading>>(motion_CurrentValueChanged);
        motion.Start();
        //...
    }
    else
        //Always have a backup plan for non-supported sensor scenario!
        //...

    base.OnNavigatedTo(e);
}

Subscribe to sensor-specific events (only those you actually need) and always have a backup plan when the sensor is not supported on the device.

3. Release the sensor at earliest possible time and unsubscribe from events:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    //If sensor were initialized
    if (null != motion)
    {
        //Unsubscribe from sensor-specific events
        motion.Calibrate -= motion_Calibrate;
        motion.CurrentValueChanged -= motion_CurrentValueChanged;
        //Stop the readings flow and release
        motion.Stop();
        motion.Dispose();
        motion = null;
    }
    base.OnNavigatedFrom(e);
}

4. Keep in mind, that the CurrentValueChanged (and other) event handlers will not arrive on UI thread. If your code need to change some on-screen element properties, use Dispatcher:

void motion_CurrentValueChanged(object sender, SensorReadingEventArgs<MotionReading> e)
{
    //Schedule UI related work to dispatcher queue
    Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            imageProjection.RotationY = e.SensorReading.Attitude.Pitch * bankLimit;
            imageProjection.RotationX = e.SensorReading.Attitude.Roll * angleOfAttackLimit;
            imageProjection.RotationZ = e.SensorReading.Attitude.Yaw * yawLimit;
        });
}

In addition to the base class members, all sensors adds some specific logic and functionality. The sample code above represents Motion sensor functionality. This sensor is a new virtual sensor which combines gyroscope, compass and accelerometer reading with some mathematic calculations needed to identify the device orientation, device movement, the gravity, etc. Those values are ready to be consumed by the applications. The motion sensors gives most accurate information since it combines all sensors and eliminates possible sensor accuracy problems when single sensor is used. This sensor is recommended to use when available.

The availability of this sensor and the readings quality depends on availability of other sensors and represented below:

Accelerometer Compass Gyroscope Motion
Yes Yes Yes Yes, full quality
Yes Yes No Yes, degraded quality
Yes No Yes No
Yes No No No

Compass sensor (aka magnetometer sensor) the following data to the application:

  • HeadingAccuracy -- The accuracy of compass heading readings in degrees. We will use this value later for compass calibration
  • MagneticHeading -- The compass heading relative to Earth’s magnetic north (provided in degrees)
  • TrueHeading -- The compass heading relative to Earth’s geographic north (provided in degrees)
  • MagnetometerReading -- The raw magnetometer reading values in microteslas (values provided in XNA’s Vector3 type. To use those readings you are required to add a reference to Microsoft.Xna.Framework assembly)

In addition, compass sensor enables application to subscribe to the Calibrate event, since magnetometer sensor which used to implement the compass is subject to external interference. Metal obstacles, high-voltage electrical installations and some electronic devices could interfere with Earth’s magnetic field and change the local magnetic field’s values. In case the sensor needs to be calibrated and the compass API fires the Calibrate event. When this event fired the application have to present the UI with instructions to perform sensor calibration. Sensor calibration performed by waving the device in figure 8 pattern:

image

The API doesn’t provide any “CalibrationComplete” notification, and it is up to developer to decide when data accuracy sufficient to the application. In general, HeadingAccuracy below 10-15 degrees should enough for most applications. This means that your calibration code should look like the follows:

void compass_Calibrate(object sender, CalibrationEventArgs e)
{
    //Show calibration instructions
    stkCalibration.Visibility = Visibility.Visible;
    //Hide compass sensor related UI
    imgRose.Visibility = Visibility.Collapsed;
    //Set "Is Calibrating" flag to consume it later
    compassCalibrating = true;
}

Then, in CurrentValueChanged event handler check if compass already calibrated to hide the calibrating instructions:

void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
{
    //Check is compass is calibrating 
    if (compassCalibrating)
    {
        //Check if current HeadingAccuracy below threshold value
        if (e.SensorReading.HeadingAccuracy < 10)
        {
            //Compass calibrated, restore the compass UI
            compassCalibrating = false;

            //The compass reading are not guaranteed to arrive in UI thread
            Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    imgRose.Visibility = Visibility.Visible;
                    stkCalibration.Visibility = Visibility.Collapsed;
                    ContentPanel.Background = new SolidColorBrush(Colors.Transparent);
                });
        }
    }

    if (!compassCalibrating)
        Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                imageRotation.Angle = e.SensorReading.TrueHeading;
            });
}

This code hides the calibration UI and display the compass UI I’m using in this sample:

image

Note: same calibration procedures applies also on motion sensor

Last new sensor in Mango is a Gyroscope. A gyroscope is a device for measuring or maintaining orientation, based on the principles of conservation of angular momentum. In Mango, Gyroscope API provides the rotational velocity around each one of 3 axis (X, Y and Z) of the device in radians per second.

Note: Since gyroscope is relatively rare sensor in current generation of Windows Phone devices it very important to have a fallback plan in case it is not supported

The GyroscopeReading class (an instance of CurrentValue) class provides us with gyroscope’s RotationRate – the rotational velocities around each one of 3 axis of the device, and Timestamp which indicates when the reading was taken.

That’s it about new sensors in Mango. Sample used to demonstrate it hosted here.

Stay tuned to the part 4 – “Camera”

Alex

Windows Phone Mango–What’s New? (“Local Data” - Part 2 of 8)

Mango provides API to use user’s Contacts and Appointments. To search for appointments and contacts we need to use the Appointments and Contacts classes located under Microsoft.Phone.UserData namespace.

In this post I’ll show how to create the sample application which will present the list of contacts and will enable user searching for specific contact. Also we will add appointments search functionality:

image

When page initialized we creating the new instance of the Contacts class:

contacts = new Contacts();
contacts.SearchCompleted += contacts_SearchCompleted;

The contacts class contains information which indicates the accounts used to provide the information. The information provided via Accounts property. It holds a collection of accounts with account kind (of StorageKind type) and account name.

In our sample the SearchCompleted event handler groups the results according to the first letter to enable binding for the presentation:

void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
    // Group all contacts according to the first letter in their display name
    var itemsSource = e.Results.GroupBy(c => c.DisplayName.First()).
                        OrderBy(group => group.Key).
                        Select(group => new ContactsGroup(group));

    // ...

}

The ContactsSearchEventArgs returns also the filter object which could be used to search for the results. Each item in Results collections holds an instance of Contact object from Microsoft.Phone.UserData namespace. It has the all the information about the contact (such as PhoneNumbers, DisplayName, EmailAddresses, Companies), the Accounts associated with this contact and indicates whether the contact is pinned to the start screen or not (IsPinnedToStart).

To start the search we need to execute the SearchAsyc method. This method asynchronously searches for contacts in the user’s contact data:

contacts.SearchAsync("Alex", FilterKind.DisplayName, null);

Method parameters specify the search query (“Alex”) and search filter (FilterKind.DisplayName) which indicates which field will be used to search.

Similarly to the Contacts, Windows Phone API provides the Appointments class in Microsoft.Phone.UserData namespace to search for user’s appointments. Appointments class initialized similarly to the Contacts class:

appointments = new Microsoft.Phone.UserData.Appointments();
appointments.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);

To start the search, invoke the SearchAsyc method which asynchronously searches for appointments that occur between the specified start date and time and end date and time.

appointments.SearchAsync(DateTime.Now, DateTime.Now.AddDays(5), null);

The code snippet searches for all appointments in all accounts in next 5 days.

The SearchCompleted event handler returns also Start and End date/time used to search for current result set. Each item in Results collections holds an instance of Appointment object from Microsoft.Phone.UserData namespace. It has the all the information about the appointment (such as Location, Organizer, Atrendees list, Subject, etc.).

Important note: you can use Windows Phone Emulator to develop only Contacts-related scenarios because the emulator has the list of sample contacts. Appointments-related scenarios are not supported on emulator and require a real device.

The sample application code hosted here.

Stay tuned for part 3 – “New Sensors & Tools Enhancements”

Alex

Windows Phone Mango–What’s New? (“Local Database” - Part 1 of 8)

Mango release adds a local database engine to the device. The database engine on the phone is based on SQL CE engine. Mango applications use LINQ to SQL for all database operations. LINQ to SQL provides an object-oriented approach to working with data and is comprised of an object model and a runtime. The database files stored in Isolated Storage on the phone and available to the application only (which means applications cannot share same database).

Suggested scenarios for local database usage in application vary between the following:

  • “Shopping list” style applications
    • Complex Schema databases -- usually has few tables (5-7), hundreds of records, but numerous relations and constraints and foreign keys
  • “Dictionary” style applications
    • Reference data – usually has a huge amount of static reference data with very few tables (2-3) and constraints. The tables (1-2 of them) holds huge amount of data (500K-1M)
  • “Local cache” for applications
    • Local cache for data fetched from cloud, sometime in combination with application specific data. Usually very few additional tables with relatively simple data; usually hundreds of records

LINQ to SQL provides object-relational mapping capabilities that allow your managed application to use Language Integrated Query (LINQ) to communicate with a relational database. LINQ to SQL maps the object model, which you express with .NET-managed code, to a relational database. When your application runs, LINQ to SQL translates language-integrated queries into database “language” and then sends them to the database for execution. When the database returns the results, LINQ to SQL translates them back to objects that you can work with in your own programming language.

LINQ to SQL works with DataContext, which defines the object model of the data. Usually DataContext defines the data using “plain old CLR objects” (POCO) and attributes convention. To create your own DataCntext classes derive them from DataContext base class. The DataContext uses managed class which defines database structure by defining table structure and mapping between the object model and the schema if the database. The mapping created by decorating objects with mapping attributes. These attributes specify database specific features such as tables, columns, primary keys, indexes, etc.

The DataContext and mapped class used to crate a local database on the phone. The code-first approach which uses managed code to define the schema and create database from it is a preferred approach for Windows Phone applications. Some key points about local database created by application:

  • A local database runs only with parent application
  • The database is not shared across different application on the device and accessible only by parent application
  • A local database supports only LINQ to SQL query mechanism; T-SQL is not supported

Let’s define simple DataContext class and simple class with mappings. First, we have to start from creating managed classes and map them into desired database schema. In our simple case the database schema will like the following picture:

image

The Divisions table definition class is very simple:

[Table]
public class Divisions
{
    public Divisions()
    {
        this._Employees = new EntitySet<Employees>(new Action<Employees>(attach_Employees), new Action<Employees>(detach_Employees));
    }

    [Column(IsPrimaryKey = true)]
    public int ID { get; set; }

    [Column]
    public string Name { get; set; }

}

And Employees table:

[Table]
[Index(Name = "NameIndex", Columns = "FirstName,LastName", IsUnique = false)]
public class Employees
{
    public Employees()
    {
        this._Division = default(EntityRef<Divisions>);
    }

    [Column(IsPrimaryKey = true)]
    public int ID { get; set; }

    [Column()]
    public int DivisionID { get; set; }

    [Column]
    public string FirstName { get; set; }

    [Column]
    public string LastName { get; set; }

    [Column(DbType = "DateTime", CanBeNull = true)]
    public DateTime? Birthday { get; set; }

    [Column]
    public bool IsActive { get; set; }

}

The only thing missing in those classes is a relation between them. In LINQ to SQL we need to add a property attributed by Association attribute. The same attribute should be added on both parts of the relation. The Division class should hold a set of entities of Employee type, thus we are adding a property of EntitySet<T> type:

private EntitySet<Employees> _Employees;
[Association(Name = "FK_EmployeesDivision", Storage = "_Employees", ThisKey = "ID", OtherKey = "DivisionID")]
public EntitySet<Employees> Employees
{
    get { return _Employees; }
    set { _Employees.Assign(value); }
}

In order to properly initialize this property let’s change the class’ constructor and add two helper methods:

public Divisions()
{
    this._Employees = new EntitySet<Employees>(
                        new Action<Employees>(attach_Employees), 
                        new Action<Employees>(detach_Employees));
}

private void attach_Employees(Employees entity)
{
    entity.Division = this;
}

private void detach_Employees(Employees entity)
{
    entity.Division = null;
}

This code takes care of proper initialization of the Employees entity for current Division. Now it is a time to change the Employee class. It has a relation to entity of Division type, thus we need to add property of type EntityRef<T>:

private EntityRef<Divisions> _Division;
[Association(Name = "FK_EmployeesDivision", Storage = "_Division", ThisKey = "DivisionID", OtherKey = "ID", IsForeignKey = true)]
public Divisions Division
{
    get { return _Division.Entity; }
    set
    {
        Divisions previousValue = this._Division.Entity;
        if (((previousValue != value)
                    || (this._Division.HasLoadedOrAssignedValue == false)))
        {
            if ((previousValue != null))
            {
                this._Division.Entity = null;
                previousValue.Employees.Remove(this);
            }
            this._Division.Entity = value;
            if ((value != null))
            {
                value.Employees.Add(this);
                DivisionID = value.ID;
            }
            else
                DivisionID = default(int);
        }
    }
}

Lastly we need to initialize the EntityRef variable – we will change the constructor:

public Employees()
{
    this._Division = default(EntityRef<Divisions>);
}

Now it’s a time to create our DataContext class:

public class SampleDC : DataContext
{
    public SampleDC(string connectionString)
        : base(connectionString)
    {
    }

    public Table<Employees> Employees;
    public Table<Divisions> Divisions;
}

From now on, the SampleDC could be used to create the database on the device and to perform operations on it.

Well, this was pretty easy, but what if you plan to use slightly bigger (and more complex) database? Fast search in my laptop returned me an AdventureWorks SQL CE sample. The schema of this database definitely makes a good candidate for Mango database feature sample:

image

(I had to minimize the schema in order to fit in on the page Smile)

So, simple ah??? The DataContext for this database will end up at ~2.5K lines of code… How about generating this DataContext manually? Clearly, that generating a DataContext for this database is not simple process. So it is not possible to use real-world databases in Windows Phone?

Well… It is clearly possible, but we need some “external” help to create the lengthy DataContext class. Let’s create a DataContext. Windows SDK provides handy utility to create LINQ to SQL DataContext for full .NET framework from SQL Server based or Compact SQL Server based databases. It called SqlMetal. We will use it to create DataContext file.

Please not, that SqlMetal doesn’t directly support Windows Phone SQL CE databases and thus SqlMetal-generated DataContext files will not compile right away in your Windows Phone projects. Use them as a start point to save a lot of coding work.

Let’s generate the ExternalDC.cs file (we will use it in sample project after the generation):

%ProgramFiles(x86)%\Microsoft SDKs\Windows\v7.0A\Bin>SqlMetal.exe 
/code:"D:\My Documents\Blog\Samples\DatabaseSample\Data\ExternalDC.cs"
"D:\My Documents\Blog\Samples\DatabaseSample\Data\ExternalDB.sdf"

After adding the generated file to the project we need to remove two constructors unsupported on Mango:

public ExternalDB(System.Data.IDbConnection connection) :
    base(connection, mappingSource)
{
    OnCreated();
}

public ExternalDB(System.Data.IDbConnection connection,
System.Data.Linq.Mapping.MappingSource mappingSource) :
    base(connection, mappingSource)
{
    OnCreated();
}

After removing them the file compiles and our complex DataContext is ready.

Once we created the DataContext we can create the database on the device. The database creation takes care of security options such as database password and encryption. Let’s create non-encrypted database first:

theDC = new SampleDC(DBName);

if (!theDC.DatabaseExists())
    theDC.CreateDatabase();

The DBName is the database file location. The file location must be according to the following format:

isostore:/DIRECTORY/FILE.sdf

To help secure the database you could password protect the database access and encrypt whole database data. When you use a password with the database, the entire database is encrypted. To encrypt the database, provide a password in the database connection string before you create the database and each time you access the database, you will need to provide the password. The DBName in case of encryption will have the connection string which must be according to the following format:

"Data Source='isostore:/DIRCTORY/FILE.sdf';Password='MySecureP@ssw0rd'"

This connection string must to be used every time you access the encrypted database.

After the local database has been created you can use LINQ to SQL queries with the DataContext instance to access the database and stored data.

LINQ to SQL is used to query the database. LINQ queries works with DataContext instance to query for data. The following code sample selects non active employees from the database (mapped through the DataContext) and orders them by LastName:

var res = from emp in mainDB.Employees
            where emp.IsActive == false
            orderby emp.LastName
            select emp;

To insert data to the database with we use two-phase approach. First we need to create a new object and add it to the DataContext and then execute the SubmitChanges function to persist the changes into the database:

Employees employee = new Employees();
employee.ID = rnd.Next();
employee.FirstName = "John";
employee.LastName = "Doe";
employee.IsActive = true;
employee.DivisionID = 103;

mainDB.Employees.InsertOnSubmit(employee);

mainDB.SubmitChanges();

Same approach works for multiple objects, but in case of multiple objects we need to create IEnumarable<T> first and call to InsertAllOnSubmit function:

List<Employees> employees = new List<Employees>();

Employees employee = new Employees();
employee.ID = rnd.Next();
employee.FirstName = "John";
employee.LastName = "Doe";
employee.IsActive = true;
employee.DivisionID = 103;
employees.Add(employee);

employee = new Employees();
employee.ID = rnd.Next();
employee.FirstName = "Nicole";
employee.LastName = "Patterson";
employee.IsActive = false;
employee.DivisionID = 104;
employees.Add(employee);

employee = new Employees();
employee.ID = rnd.Next();
employee.FirstName = "Vito";
employee.LastName = "Carleone";
employee.IsActive = true;
employee.DivisionID = 101;
employees.Add(employee);

mainDB.Employees.InsertAllOnSubmit(employees);
mainDB.SubmitChanges();

Updateing and deleting data requires three-stage process - first we need to find an object (or objects) to update/delete, then update/delete it from DataContext and finally SubmitChanges.

Update:

var res = from emp in mainDB.Employees
            where emp.FirstName == "Michael" && emp.LastName == "Jackson"
            select emp;

Employees employee = res.FirstOrDefault();

if (null != employee)
    employee.IsActive = !employee.IsActive;
mainDB.SubmitChanges();

Delete:

var res = from emp in mainDB.Employees
            where emp.FirstName == "Nicole" && emp.LastName == "Patterson"
            select emp;

Employees employee = res.First();

if (null != employee)
    mainDB.Employees.DeleteOnSubmit(employee);

mainDB.SubmitChanges();

The approach used to update/delete multiple records similar to one used to insert multiple records. Those method used to delete multiple records called DeleteAllOnSubmit.

Let’s get back to the AdventureWorks database. Clearly that in case of such big and complex database with decent amount of “system” data it is not possible to create the database on the device. In such case we need to package the database file as a Content resource of the application, copy it to application’s Isolated Storage and use generated DataContect to access the data:

image

The following code snippet pulls the application resource stream, sends it to helper method which returns the stream content as array of bytes and finally saves those bytes to application’s Isolated Storage.

public static void CreateExternalDatabase(string DBName)
{
    Stream str = Application.GetResourceStream(new Uri("Data/" + DBName, UriKind.Relative)).Stream;

    using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
    {
        IsolatedStorageFileStream outFile = isoStore.CreateFile(DBName);

        outFile.Write(ReadToEnd(str), 0, (int)str.Length);
        str.Close();
        outFile.Close();
    }
}

public static byte[] ReadToEnd(Stream stream)
{
    long originalPosition = stream.Position;
    stream.Position = 0;
    try
    {
        byte[] readBuffer = new byte[4096];
        int totalBytesRead = 0;
        int bytesRead;

        while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
        {
            totalBytesRead += bytesRead;
            if (totalBytesRead == readBuffer.Length)
            {
                int nextByte = stream.ReadByte();
                if (nextByte != -1)
                {
                    byte[] temp = new byte[readBuffer.Length * 2];
                    Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                    Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                    readBuffer = temp; totalBytesRead++;
                }
            }
        }

        byte[] buffer = readBuffer;

        if (readBuffer.Length != totalBytesRead)
        {
            buffer = new byte[totalBytesRead];
            Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
        }

        return buffer;

    }
    finally
    {
        stream.Position = originalPosition;
    }
}

Accessing the database created such way is similar to database created from DataContext on the device:

externalDB = new ExternalDB(ExternalDBFileName);
var products = (from p in externalDB.Products
                select p).Take(10);

Last part of this post will focus on database schema updates. Normal Windows Phone application lifestyle includes updating the application from time to time. This also could introduce changes in the database schema. In most case we want to preserve user data stored in the database, that’s why we need to Update the database using special class – DatabaseSchemaUpdated from Microsoft.Phone.Data.Linq namespace. The DatabaseSchemaUpdater class can perform additive changes to the database, such as adding tables, columns, indexes or associations. For more complex changes, you will need to create a new database and copy the data to the new schema, as applicable. The DatabaseSchemaUpdater class provides a DatabaseSchemaVersion property that you can use to programmatically distinguish different versions of your database:

DatabaseSchemaUpdater schemaUpdater = theDC.CreateDatabaseSchemaUpdater();

if (schemaUpdater.DatabaseSchemaVersion < 2)
{
    //Incompatible change detected, create new database, 
    //copy data from old database to new and delete old database
    MigrateDataToNewDatabase(theDC);
}
else if (schemaUpdater.DatabaseSchemaVersion == 2)
{
    //Compatible change. Add new column to existing table
    //NOTE: IsRetired is a new property defined in Employees 
    schemaUpdater.AddColumn<Employees>("IsRetired");
}

The DatabaseSchemaUpdater allows adding Table, Column, Index and Association. The new additions have to be defined in the corresponding DataContext class first. In the previous code snippet, the updated Employee class has additional column, named IsRetired:

[Column]
public bool IsRetired { get; set; }

This is it for now…

Sample used to demonstrate those features hosted here.

Stay tuned for part 2 – “Local Data Access”

Alex

Windows Phone Mango–What’s New? (“Overview” - Part 0 of 8)

The Beta version of “Windows Phone Mango” tools release and it is a time to see what is expected from developers point of view.

This post is a first part of multi-part “What’s new” series which focuses on new features of “Windows Phone Mango” (or shortly Mango from this point). The Mango brings to the developer many features which we missed from initial release of Windows Phone 7 (or shortly RTM from this point). The “formal” features list includes the following features:

  • Multi-tasking
    • Fast Application Switch/Resume (FAS)
    • Background Agents (Audio, File Transfers, Periodic processing)
  • Enhanced Phone Framework
    • Silverlight 4
  • XNA & Silverlight Integration
  • Sensors & Devices
    • Motion Sensor
    • Gyroscope
    • Magnetometer (aka Compass)
    • Direct Camera access
  • Local Database
    • SQL CE
  • Local Data access
    • Appointments
    • Contacts
  • Improvements in Push Notifications mechanism
    • Local push notifications
    • Secondary tiles
    • Flip tiles
  • Networking improvements
    • Sockets
  • Performance Improvements
  • Tooling improvements
    • Emulator now includes Accelerometer & Location emulation
    • Profiling

Most of those improvements will be covered in dedicated post (some will share a post with others) in upcoming post series.

 

Stay tuned for part 1 – Local Database.

Alex

Windows Phone “Mango” Developer Tools Beta

Windows Phone Developer Tools for Windows Phone “Mango” (7.1) Beta release announced and available for general download here:

http://go.microsoft.com/?linkid=9772716

Documentation link:

http://msdn.microsoft.com/en-us/library/hh237343(v=VS.96).aspx

 

The Beta tools provides all tooling necessary to target the upcoming Windows Phone “Mango” release, in addition to productivity enhancements, such as an app profiler, an improved emulator. Features of the WPDT 7.1 include:

  • Profiler – A profiler that allows you to identify and resolve performance problems.
  • Improved Emulator – The new emulator allows you to emulate provide sensor input, including feeding GPS information and accelerometer data.
  • Multi-targeting – lets you specify the version of the Windows Phone OS that will run your app. This allows you to continue to develop your apps that target the Windows Phone OS 7.0, or target the new “Mango” release.
  • Support for Windows Phone OS 7.1 – Build mobile apps that take advances in the upcoming Windows Phone OS, including:
    • Additional sensors (camera; compass; gyro)
    • Background Agents
    • Fast Application Switching
    • IE9 Web Browser Control
    • Live Agents, making use of live tile and notification enhancements
    • Silverlight 4
    • Silverlight / XNA Interop
    • Sockets
    • SQL CE

Note: Applications written with 7.1 will not be allowed on the current Marketplace and using Mango APIs are not permitted in 7.0 applications.

 

Stay tuned for more information and in-depth features overview,

Alex

WP7 Acceleration Week in Microsoft Israel R&D Center

Seems this week dedicated to announcements Winking smile because I have additional announcement to made!

Next week I will deliver many Windows Phone 7 & Windows Phone “Mango” sessions as a part of “WP7 Acceleration Week”.

 

The week agenda is as follows:

Sunday, May 22nd 09:00-13:30

· Windows Phone 7 Bootcamp and Demo – An overview of the Windows Phone 7 platform and its abilities. Presented by Sela.

· Mobile Application UI – Principles of good mobile UI. Presented by Balora.

· Introduction to WP7 Metro UI – An in-depth look at the unique Windows Phone UI. Presented by Balora and Sela.

· Sensors – How to use the phone’s sensor capabilities to create richer application possibilities. Presented by Sela.

· Push Notification – Utilizing push notification effectively in a Windows Phone environment. Presented by Sela.

· On Stage App Development – The session will show how an application is developed start to finish. Presented by Sela.

Monday, May 23rd: 17:00-19:00

· Monetizing Mobile Applications –Effective app monetization techniques. Presentation by innerActive.

· Mobile App Analytics – The importance of utilizing analytics for app developers. Presentation by Guy Merin, Microsoft.

· The Nokia View –As Microsoft and Nokia engage in their partnership, a representative of the Nokia Developer Forum will provide an overview of how Nokia works with the developer community

Wednesday, May 25th: 17:00-19:00

· Game Developer Session: Game Development with XNA – Special deep-dive on XNA development for games by Sela.

Thursday, May 26th: 17:00-20:00

· What’s new with Windows Phone 7.5 – The enhanced abilities that will be available in the next Windows Phone release, which will be available for developers at the end of May. Presentation by Sela.

· Windows Phone Road Map – What lies ahead for Windows Phone. Presentation by the Microsoft R&D team.

All “Sela” sessions will be delivered by me.

 

This week is an Israel Mobile & Communication Association & Microsoft Israel R& D Center sponsored event and is free for all developers!

For more information please follow this link:

http://imaworld.org/?CategoryID=790

Registration is free, but places are extremely limited. To register visit this page:

http://imaworld.org/?CategoryID=791

 

See you there!

Alex

Upcoming Windows Phone 7, Windows Phone “Mango” and Advanced Silverlight Trainings in Redmond

I have a confession – I’m very excited those days!

In 3 weeks I’m flying to Redmond, WA to deliver 3 new brand courses for advanced software developers. I will present “First Look” material about hottest topics (IMO) for developer community:

1. Advanced Windows Phone 7

2. Windows Phone “Mango”

3. Advanced Silverlight

These trainings will all be held at Bellevue College campus the week of June 6-10, 2011.

Map picture

For information regarding this series, including registration information, please visit the following links:

Windows Phone “Mango” – What’s New for Developers – Level 200, targeted for current phone developers

    1. Date: 1 Day Course; Friday, June 10, 2011; 9:00 AM – 4:30 PM
    2. Location: Bellevue College, Advanced Education Center
    3. Instructor: Alex Golesh, SELA College Tel Aviv
    4. Description: Windows Phone “Mango” is Microsoft’s newest version of mobile phone. This one day instructor-led course introduces the new features added to Windows Phone to enable additional scenarios which were not possible with previous version and much requested by developers. The course focuses on the new features, best practices of implementing them for Windows Phone 7.5, “how-to” and “tips and tricks”.

 

Windows Phone 7 Application Platform – Technical Deep Dive – Level 200, targeted for current application developers

    1. Date: 2 Day Course; Wed-Thurs, June 8-9, 2011; 9:00 AM – 4:30 PM
    2. Location: Bellevue College, Advanced Education Center
    3. Instructor: Alex Golesh, SELA College Tel Aviv
    4. Description: Windows Phone 7 is Microsoft’s newest mobile phone. It is different than most phones out there, and offers a lot of opportunities for your application to get to the global markets quickly. This day long workshop goes beyond the details of building applications and games for Windows Phone, but gives you the best practices necessary to build the type of compelling applications and games for Windows Phone 7 that users want and willing to pay for. In this workshop, we'll go way beyond the basics overviews, and give you detailed information and guidance on all of the details, from UX design, to software patterns, to dealing with data and performance optimization.

 Advanced Silverlight 4 – Line of Business Application Development + What’s New in Silverlight 5 – Level 300, targeted for current Silverlight developers

    1. Date: 2 Day Course; Mon-Tues, June 6-7, 2011; 9:00 AM – 4:30 PM
    2. Location: Bellevue College, Advanced Education Center
    3. Instructor: Alex Golesh, SELA College Tel Aviv
    4. Description: This two day instructor-led course provides students with the knowledge and skills to develop Line of Business applications with Microsoft Silverlight through a variety of available development tools and techniques. Second course day introduces new features and concepts being introduced with the new version of the technology – Silverlight 5. The course focuses on best practices for LOB application development, how-to’s and “tips and tricks”.

I’m looking forward to these 3 in-person courses! I believe that it comes at the right time and in the right place!

If you are in town – join me at Bellevue College or spread the word between your friends who want to learn this brand new content!

 

See you there,

Alex