Over 2 years of Xamarin

I have held radio silence for over 2 years because I am having a blast doing nothing but Xamarin based development. During this time I have been fully involved in building music apps that I actually use in my everyday life. I struggled with the pains and gained a love/hate relationship with the development tools I use. I work primarily on a Mac since the products we build only target iOS and Android and I adore Xamarin Studio, it’s super fast and simple and it reminds me of the good old bad days of Visual Studio from over a decade ago where it was pretty much just a big text editor with a few fancy features. Xamarin Studio of course has its ups and downs and sometimes it just doesn’t want to cooperate. Every time a new “stable” version is out I needed to make sure that I only update during non-busy days as I risk losing all productivity if I install an update with breaking changes, or an update that is just simply broken. Some updates do break stuff! Some breaking changes are minor and easy to fix and some are rather complex to work around the problem. I remember once, our builds broke because the command line build tooling somehow got deprecated suggesting us to move from MDTool to XBuild, although the change sounds trivial it costed me a full day of work to update all our build scripts and double check every single build configuration that they work as they should in our build servers

On top of having a full time position doing Xamarin development for a Music Services company, I also do a few side project. For these projects I use Xamarin.Forms as it shows a lot of promise. The early versions were terrible but they eventually got much better. For simple UI requirements its absolutely perfect. With Xamarin.Forms you can create a cross platform UI that you only write once using either a flavor of XAML or in code (using C# in my case). In Xamarin.Forms you can either take advantage of the sharable UI tooling so you only have to write the UI code once and have it rendered natively on iOS, Android, and Windows Phone, or you can create custom renderers that allow you fully control using the API’s of the platforms you target to implement the control or the entire screen. When you end up implementing the entire app using custom renderers then Xamarin.Forms starts making less sense for what you’re trying to build, but for Line-of-Business apps its perfect. I can really see a big future in Xamarin.Forms

Knowing and understanding the platform is always better than relying on cross platform tools. I have mostly been working on multi-platform solutions throughout my career and the experience I gained has been a great advantage for me as I understand how a lot of things work and why API’s do what they do. A good example of such cross platform issues is working with Bitmaps. In a nutshell, a bitmap is an array of 32-bit integers containing the Red-Blue-Green-Alpha pixel information. If you do cross platform development and image processing you will need to ensure that the order of the pixel information bytes are uniform so that the algorithm you work with will work across all the targetted platforms. This might come as a surprise to some but pixel information is stored differently for every platform’s Bitmap API, for example, iOS uses Red-Blue-Green-Alpha, Android uses Alpha-Red-Blue-Green, and Windows uses Blue-Green-Red-Alpha. All these platforms have API’s that allow you retrieve the pixel buffer (the array of 32-bit integers) in a single call avoiding calling using slow API’s like GetPixel(x,y) hundreds or even thousands of times. Too make things even more fun the Xamarin.Forms.Color structure has a static helper method called FromUint(uint argb) but the documentation (at the current time of writing) describes the method as Returns a new Color with the requested RGBA value and the method parameter is described as A uint that represents the ARGB value of the color and the return value is described as An RGBA color. So that was a bit confusing! Eventually Xamarin will correct these small details or developers will just have to live with them

I just ended a side project and will probably not take on any new side projects for a while so I can spend more time learning new awesome stuff, or in some case understanding old awesome stuff. I have a few hobby projects that I have been intending to open source for a while so I’ll probably finish those up and finally publish them. I had some a bit success with some open source projects such as SQL Compact Query Analyzer (50k downloads), SQL Compact Code Generator (15k downloads), and ResW File Code Generator (4k downloads), all which had very constructive and positive reviews. I always enjoyed building developer tools and I hope to get more of that done in the nearest future

My future is Xamarin

I have been creating software for handheld devices for over a decade now. I’ve seen interesting things come and go and also witnessed a couple of failures. A great part of my mobile development career involved consulting and I had loads of fun working with some very smart people doing all sorts of interesting stuff. But for the past year or so I felt like I fell into a deep whole. Normally I would provide consulting services for up to 6 months then move on to something else, but my last project was not the case. It was retailer solution and was not really interesting, not at all challenging, and was mostly tedious, and to make it worse I was targeting a 10 year old platform and needed to support an even older one. I first went along with this because the company was going through a hard time and could really use some revenue, at that time we had just let go of 1/3 of our staff and I felt lucky that I got to keep my job. I did my job the best I could even and delivered what needed to be shipped. As the project progressed and the requirement changes got out of hand I found myself in an endless loop of fixing then breaking then fixing stuff. Sometimes in life you just have to suck it up and do your job since after all it pays the bills, keeps a roof over our heads, and puts food on the table. This project has taken all of my time and energy. It was the main reason I have not posted a single article for an entire year!

During this time I paid a lot of attention (more than usual) to what was going on in the mobile space and I have grown an interest in Xamarin. I’ve seen more and more people adapt Xamarin and after trying it in a few small projects I could really see why. This means a lot coming from me since I am a huge fan of native platform development. I’ve done Android projects before where I used Java + Eclipse and iOS projects where I used Objective-C + XCode. But after seeing and trying out Xamarin, thanks to my experience with Android and iOS, I found myself immediately being productive. I love the fact that I can just use the official Android or iOS documentation pages and be able to implement it directly using Xamarin.
So after months of considerations I have decided to take a break from consulting and take on a full time position for a company called 24/7 Entertainment where I will be doing Xamarin development. I have worked with the company in the past where I helped them with some Windows Phone and Store music apps. I know the team from past work experiences and I know that they are loads of fun to work with and are very passionate about what they do. They believe in their products and all share common goals. They follow modern software development practices and use the latest and the greatest development tools and hardware. This job is going to be fun, challenging, and simply great! I hope to learn, contribute, and have a blast!

Integrating with the Windows Phone 8 Lock Screen

A nice new feature in Windows Phone 8 is integration with the lock screen. As a developer, you can now display notification icons the same way the Outlook app displays New Mail notifications. You can also change the background image of the lock screen from your app. The information used for displaying notification is the exact same information that an app uses to display notifications on the app’s primary tile regardless if the app is pinned to the start screen or not

Notification Icon

To display an icon on the lock screen you must follow a small set of strict rules on how your image file should be. The image has to be a 38 x 38 PNG image that contains only white pixels and some levels of transparency. Yes, I know it’s a bit strict but it makes sense as the icon notifications are designed to be very discreet.

App Manifest

You need to define a few extensions to let the operating system allow your app to integrate with the lock screen. So here’s what we need to do, open the WMAppManifest.xml file using an XML editor, to do this right click on the WMAppManifest.xml file and select Open With, and use the XML (Text) Editor. First, we need to define the <DeviceLockImageURI> element in the primary token. The DeviceLockImageURI describes which image file to display in the lock screen as an icon. To define DeviceLockImageURI, insert the following element in the <PrimaryToken>

<DeviceLockImageURI IsRelative="true"
                    IsResource="false">AssetsYourLockImage.png</DeviceLockImageURI>

Then, insert the following lines after the between the <Tokens> and <ScreenResolutions> definitions

<Extensions>
  <Extension ExtensionName="LockScreen_Notification_IconCount"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
  <Extension ExtensionName="LockScreen_Notification_TextField"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
  <Extension ExtensionName="LockScreen_Background"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
</Extensions>

Lock screen settings

Before our app can display notifications we need to configure our Lock Screen settings to allow the type of notification that we are interested in displaying. Currently an app can display 3 types of notifications: background image; detailed status; and quick status. Detailed status is similar to the textual calendar notifications that are displayed using the Outlook Calendar app. Quick status is similar to the way the Outlook Mail app displays notifications, an icon and a count indicator.

To configure the device to display notifications from your app, go to the settings app and select Lock screen

settings

In the lock screen settings, choose the notification type that will display notifications from our app

image

For this example we’ll show a quick status notification

quick status on

Code

To update the background image of the lock screen we need use the LockScreen class of the UserProfile API. First we check if the user configured the app to be able to set the background of the lock screen, we can do this through LockScreenManager class. If the app isn’t allowed to change the lock screen background then we can open the lock screen settings page.

Lock screen background (C#)

if (await LockScreenManager.RequestAccessAsync() == LockScreenRequestResult.Granted)
{
    var uri = new Uri(“ms-appx:///Assets/LockScreenImage.png”, UriKind.Absolute);
    LockScreen.SetImageUri(uri);
}
else
{
    // Open the Settings -> Lock Screen settings
    await Launcher.LaunchUriAsync(new Uri(“ms-settings-lock:”));
}

To display an icon notification just update the primary application tile with a notification. We can do this by using the ShellTile API

Display notification (C#)

var tile = ShellTile.ActiveTiles.First();
var data = new FlipTileData
                {
                    Count = 1,
                    Title = “Lock Screen Demo”
                };
tile.Update(data);

To clear the notification just update the primary application tile to its original state

Clear notification (C#)

var tile = ShellTile.ActiveTiles.First();
var data = new FlipTileData
                {
                    Count = 0,
                    Title = “Lock Screen Demo”
                };
tile.Update(data);

Pretty simple isn’t it?

Testing on the Emulator

To test on the Windows Phone emulator you can use the Simulation Dashboard which integrates directly into Visual Studio. To launch this, go to Tools –> Simulation Dashboard. You can use this tool to Lock and Unlock the emulator to test your apps lock screen integration

image

I hope you found this interesting. You can grab the source code here

Using the Windows Phone Custom Contact Store

In previous versions of Windows Phone, you could always query the contact store to retrieve contact or calendar items. During that time I always wondered why I couldn’t just create my own contacts that can be shared with other applications and accessed through the People Hub. I guess more people had this problem and in Windows Phone 8 this has been addressed. Windows Phone 8 introduced the custom contact store in which apps can create contacts that are accessible from the People Hub and from other apps. Items in the custom contact store may only be modified by app that created them

How to create contacts in Windows Phone 8

In this section I would like to demonstrate how to use the custom contact store API. In order to do so we’ll create a UI that accepts the display name, email address, and mobile phone number. To make it a bit more fancy, we’ll add a feature that accepts a photo which can be loaded either from the camera or the media library

So here’s the code…

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

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="CUSTOM CONTACT STORE" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0" />
            <TextBlock Text="Sample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Text="Display Name" VerticalAlignment="Center" />
                    <TextBox Grid.Column="1" Name="displayName" />
                    <TextBlock Grid.Row="1" Text="Email" VerticalAlignment="Center" />
                    <TextBox Grid.Row="1" Grid.Column="1" Name="email" />
                    <TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Mobile" />
                    <TextBox Grid.Row="2" Grid.Column="1" Name="mobile" />
                </Grid>
                <Button Content="Attach New Photo" Click="AttachNewPhotoClicked" />
                <Button Content="Attach Existing Photo" Click="AttachExistingPhotoClicked" />
                <Button Content="Save Contact" Click="AddClicked" />
            </StackPanel>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

Code Behind (C#)
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Tasks;
using Windows.Phone.PersonalInformation;

namespace CustomContactStore
{
    public partial class MainPage
    {
        private Stream photo;

        public MainPage()
        {
            InitializeComponent();
        }

        private async void AddClicked(object sender, RoutedEventArgs e)
        {
            var store = await ContactStore.CreateOrOpenAsync();
            var contact = new StoredContact(store)
                              {
                                  DisplayName = displayName.Text
                              };

            var props = await contact.GetPropertiesAsync();
            props.Add(KnownContactProperties.Email, email.Text);
            props.Add(KnownContactProperties.MobileTelephone, mobile.Text);

            if (photo != null)
                await contact.SetDisplayPictureAsync(photo.AsInputStream());

            await contact.SaveAsync();

            if (photo != null)
                photo.Dispose();
        }

        private void AttachNewPhotoClicked(object sender, RoutedEventArgs e)
        {
            var task = new CameraCaptureTask();
            task.Completed += OnTaskOnCompleted;
            task.Show();
        }

        private void OnTaskOnCompleted(object o, PhotoResult result)
        {
            photo = result.ChosenPhoto;
        }

        private void AttachExistingPhotoClicked(object sender, RoutedEventArgs e)
        {
            var task = new PhotoChooserTask();
            task.Completed += OnTaskOnCompleted;
            task.Show();
        }
    }
}

To create a custom contact we need to use the ContactStore API, we create an instance of this using the helper method CreateOrOpenAsync(). Now that we have an instance of the contact store, we create an instance of a StoredContact and set the DisplayName property to the value of the display name entered in the UI. The StoredContact object is very limited but we can add KnownContactProperties such as Email and MobileTelephone. This is done by using the GetPropertiesAsync() method of the StoredContact instance. The photos can be attached using the CameraCaptureTask or the PhotoChooserTask. We attach the photos by calling the SetDisplayPictureAsync() method of the StoredContact instance. The API’s for the custom contact store are pretty straight forward and easy to use.

Manifest

The custom contact store requires the ID_CAP_CONTACTS capability, we should enable that in the WMAppManifest.xml file. In order to that, in the Visual Studio Solution Explorer, expand the project properties folder and double click the WMAppManifest.xml file. This will open the new UI editor for the manifest file. Go to the Capabilities tab and enable the ID_CAP_CONTACTS

id_cap_contacts

Once the manifest file has been updated the app should be able to launch.

The user interface looks like this:

Custom Contact Store

Once the contact is created it will be available in the People Hub

People Hub

When the contact is viewed from the People Hub the owner of the contact will be displayed on top

Custom Contact

I hope you found this useful. You can check out the source code using the link below

The missing ResWFileCodeGenerator custom tool for Visual Studio 2012

I’ve been doing quite a lot of Windows Store Apps on Windows 8 lately. Ever since I started I always seemed to miss the ResXFileCodeGenerator custom tool. This is because in WinRT when you want to load a localized string in code then you will have to do something like this:

var resources = new ResourceLoader();
var localizedString = resources.GetString("SomeResourceName");

This of course can easily lead to a lot of errors. In my case I got a little to eager while refactoring and forgot to notice that I was also changing hard coded strings. This broke the code quite a lot. Because of this frustration I decided to implement my own custom tool since Microsoft didn’t provide one

The project is open source and is available at CodePlex. Here’s a preview of the description which I took directly from my CodePlex project site.

Project Description
A Visual Studio 2012 Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.

Features
– C# code generator
– VB.NET code generator

Visual Studio 2012 Custom Tool (C#)

Visual Studio 2012 Custom Tool (VB)

Resource File Contents

C# Usage

private string test1, test2, test3;

private void LoadLocalizedStrings()
{
test1 = App1.LocalizedResources.Resources.Test1;
test2 = App1.LocalizedResources.Resources.Test2;
test3 = App1.LocalizedResources.Resources.Test3;
}

Visual Basic Usage

Dim test1, test2, test3

Private Sub LoadLocalizedStrings()
test1 = AppVb.LocalizedStrings.Resources.Test1
test2 = AppVb.LocalizedStrings.Resources.Test2
test3 = AppVb.LocalizedStrings.Resources.Test3
End Sub

Generated C# Code

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18010
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------
// <auto-generatedInfo>
// This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
// ResW File Code Generator was written by Christian Resma Helle
// and is under GNU General Public License version 2 (GPLv2)
//
// This code contains a helper class exposing property representations
// of the string resources defined in the specified .ResW file
//
// Generated: 11/08/2012 22:41:22
// </auto-generatedInfo>
// --------------------------------------------------------------------------------------------------
namespace App1.LocalizedResources
{
using Windows.ApplicationModel.Resources;


public partial class Resources
{

private static ResourceLoader resourceLoader = new ResourceLoader();

/// <summary>
/// Localized resource similar to "Test 1 value"
/// </summary>
public static string Test1
{
get
{
return resourceLoader.GetString("Test1");
}
}

/// <summary>
/// Localized resource similar to "Test 2 value"
/// </summary>
public static string Test2
{
get
{
return resourceLoader.GetString("Test2");
}
}

/// <summary>
/// Localized resource similar to "Test 3 value"
/// </summary>
public static string Test3
{
get
{
return resourceLoader.GetString("Test3");
}
}
}
}

Generated Visual Basic Code

'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.18010
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------

Option Strict Off
Option Explicit On

Imports Windows.ApplicationModel.Resources

'--------------------------------------------------------------------------------------------------
'<auto-generatedInfo>
' This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
' ResW File Code Generator was written by Christian Resma Helle
' and is under GNU General Public License version 2 (GPLv2)
'
' This code contains a helper class exposing property representations
' of the string resources defined in the specified .ResW file
'
' Generated: 11/12/2012 21:30:52
'</auto-generatedInfo>
'--------------------------------------------------------------------------------------------------
Namespace AppVb.LocalizedStrings

Partial Public Class Resources

Private Shared resourceLoader As ResourceLoader = New ResourceLoader()

'''<summary>
'''Localized resource similar to "Test 1 value"
'''</summary>
Public Shared ReadOnly Property Test1() As String
Get
Return resourceLoader.GetString("Test1")
End Get
End Property

'''<summary>
'''Localized resource similar to "Test 2 value"
'''</summary>
Public Shared ReadOnly Property Test2() As String
Get
Return resourceLoader.GetString("Test2")
End Get
End Property

'''<summary>
'''Localized resource similar to "Test 3 value"
'''</summary>
Public Shared ReadOnly Property Test3() As String
Get
Return resourceLoader.GetString("Test3")
End Get
End Property
End Class
End Namespace

Parenthood

Once again I have taken a break from blogging. Parenting and my new family has been my absolute top priority and I’ve been having a hard time finding the time to write articles. I really enjoy spending time with my son and wife and I take advantage of every possible moment to do so.

I ended up at a schedule that starts around 5:30 AM in which my son wakes up, and wakes me up. I go and start preparing some breakfast for him. We then have a cozy morning playing around the house. I drop him off at day care as late possible (in my case 9:00 AM) and then drive to the office, or to a customer, or back home if I’m working from home. I pick my son up at between 3:00-4:00 PM and spend time with him and my wife until around 6:30 PM (this is his bed time and I’m very lucky that he has no trouble sleeping). From around 6:30 to 8:00-9:00 PM I spend some time with my wife discussing how our days went and do some planning for the following days. My wife goes to bed a bit early, and when that happens I go back to work. Since I drastically shortened by day, I need to do quite a bit of catching up at night. I usually work an extra 2-3 hours more at night, then I have an hour or 2 to give my mind a rest or work on a hobby project. My day usually ends between 12:30 AM and 2:00 AM. I need at least 4 hours of sleep to recharge for the next day, otherwise I won’t be able to last a full week on my schedule.

Hence the break from blogging 🙂

Accessing the Accelerometer from HTML5 and Javascript with Windows Phone 7

In my previous post I discussed how to have Javascript code hosted in a WebBrowser control execute .NET code in the host application and vice versa. I also demonstrated how to retrieve and display device status information using HTML5 hosted in a WebBrowser control.

For this sample I would like to demonstrate how to access the Accelerometer sensor from HTML5 and Javascript. To make things more interesting, the Accelerometer reading data will be constantly updated every 100 milliseconds and .NET code will repeatedly call a Javascript method as Accelerometer reading data gets updated

And here’s the code…

Default.html (HTML5 + Javascript)

The code below is going to be used as a local html file that is to be copied to isolated storage. Let’s put this in a folder called HTML

<!DOCTYPE html>

<html>

<head>

    <meta name="viewport" content="width=480, height=800, user-scalable=no" />

    <meta name="MobileOptimized" content="width" />

    <meta name="HandheldFriendly" content="true" />

    <title>HTML5 and Windows Phone 7</title>

    <style>

        body

        {

            color: White;

            background-color: Black;

            font-family: ‘Segoe WP Semibold’;

            text-align: left;

        }

        h3

        {

            font-size: 20pt;

        }

        input

        {

            color: #ffffff;

            background-color: #000000;

            border: 2px solid white;

            vertical-align: baseline;

            font-size: 17pt;

            min-width: 40px;

            min-height: 40px;

            margin: 5;

        }

    </style>

</head>

<body onload="onLoad()">

    <div>

        <h3>

            X:</h3>

        <input id="x" type="text" value="0" />

        <h3>

            Y:</h3>

        <input id="y" type="text" value="0" />

        <h3>

            Z:</h3>

        <input id="z" type="text" value="0" />

    </div>

    <script type="text/javascript">

        function onLoad() {

            window.external.notify("startAccelerometer");

        }

 

        function accelerometerCallback(x, y, z) {

            document.getElementById("x").value = x;

            document.getElementById("y").value = y;

            document.getElementById("z").value = z;

        }

    </script>

</body>

</html>

 

MainPage.xaml

The code below is the main page of the Silverlight application that will host the HTML content

<phone:PhoneApplicationPage x:Class=”PhoneApp.MainPage”
                           xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
                           xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
                           xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
                           xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
                           xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
                           xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
                           mc:Ignorable=”d”
                           d:DesignWidth=”480″
                           d:DesignHeight=”768″
                           FontFamily=”{StaticResource PhoneFontFamilyNormal}”
                           FontSize=”{StaticResource PhoneFontSizeNormal}”
                           Foreground=”{StaticResource PhoneForegroundBrush}”
                           SupportedOrientations=”Portrait”
                           Orientation=”Portrait”
                           shell:SystemTray.IsVisible=”True”
                           Loaded=”PhoneApplicationPage_Loaded”>
    <Grid x:Name=”LayoutRoot”
         Background=”Transparent”>
        <phone:WebBrowser Name=”browser”
                         IsScriptEnabled=”True”
                         Source=”HTML/Default.html”
                         ScriptNotify=”browser_ScriptNotify” />
    </Grid>
</phone:PhoneApplicationPage>

MainPage.xaml.cs

And here’s the code behind the xaml file

public partial class MainPage : PhoneApplicationPage

{

    private Microsoft.Devices.Sensors.Accelerometer accelerometer;

 

    public MainPage()

    {

        InitializeComponent();

    }

 

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

    {

        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())

        {

            if (!store.DirectoryExists("HTML")) store.CreateDirectory("HTML");

            CopyToIsolatedStorage("HTML\Default.html", store);

        }

    }

 

    private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true)

    {

        if (store.FileExists(file) && !overwrite)

            return;

 

        using (Stream resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream)

        using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))

        {

            int bytesRead;

            var buffer = new byte[resourceStream.Length];

            while ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)

                fileStream.Write(buffer, 0, bytesRead);

        }

    }

 

    private void browser_ScriptNotify(object sender, NotifyEventArgs e)

    {

        if (e.Value == "startAccelerometer")

        {

            if (accelerometer == null)

            {

                accelerometer = new Microsoft.Devices.Sensors.Accelerometer { TimeBetweenUpdates = TimeSpan.FromMilliseconds(100) };

                accelerometer.CurrentValueChanged += (o, args) => Dispatcher.BeginInvoke(() =>

                {

                    var x = args.SensorReading.Acceleration.X.ToString("0.000");

                    var y = args.SensorReading.Acceleration.Y.ToString("0.000");

                    var z = args.SensorReading.Acceleration.Z.ToString("0.000");

 

                    browser.InvokeScript("eval", string.Format("accelerometerCallback({0},{1},{2})", x, y, z));

                });

                accelerometer.Start();

            }

        }

    }

}

What happens in the code above is that a Javascript method is executed that notifies the host application telling it to start the Accelerometer when the HTML has loaded. We then add an event handler to the Accelerometers CurrentValueChanged event that invokes the accelerometerCallback Javascript method and passing in Accelerometer reading data as the arguments. Notice that I use eval as the Javascript method to invoke and passing the method call as an argument, this is because the accelerometer reading data is retrieved on a worker thread and for some reason an unknown system error occurs even when executing code on the UI thread through the Page Dispatcher.BeginInvoke() method. I figured out that using eval was the only way to execute Javascript code from a .NET worker thread.

I hope you found this useful. You can grab the full source code for the example here:

Integrating HTML5 and Javascript with Windows Phone 7

Everyone, everywhere is talking about HTML5 these days. I myself did a recent talk at the Danish Developer Conference 2012 on Windows Phone and HTML5. I get the point and I see the power and beauty of HTML5. But, HTML5 is as far as I can see not entirely ready yet and as for mobile applications, I would always choose writing a native application that takes full advantage of the platform and not just an application that runs in a browser, even if the the browser component is hosted in a native application. I think developers should really learn to appreciate the platform more.

In this article I would like to explain how to integrate HTML5 + Javascript in a Windows Phone application and the same demonstrate how to call a .NET method from Javascript and how to call a Javascript method from .NET

So here’s what we need to do to get started:

  1. Create a Windows Phone Silverlight application
  2. Add a WebBrowser component on the main page
  3. Set the IsScriptEnabled property of the WebBrowser component to true
  4. Add an event handler to the ScriptNotify event of the WebBrowser component
  5. Create a folder on the project called HTML and add the HTML, Javascript, and Stylesheet assets to this folder
  6. Write code to copy the HTML related assets to IsolatedStorage
  7. Set the source of the WebBrowser component to the main HTML page
Simple isn’t it?

How it works

The steps above really do seem to be quite simple, and yes it really is. For Javascript to call into the host of the WebBrowser control we can use the window.external.notify() method. This is the same approach for having Javascript code execute code in the host application in other platforms. The window.external.notify() method takes a string which can be used to contain meta data that describes what you want the host to do. And for .NET code to execute Javascript code we use the InvokeScript() method of the WebBrowser control. The InvokeScript() method takes a string parameter that describes the Javascript method to execute, and a collection of strings that describe the arguments to be passed to the Javascript method to execute. If the method that will invoke a javascript function from the host is running on a non-UI thread (worker thread) then the best approach to using this method is by calling InvokeScript(“eval”, “methodName(args1,args2,args3)”) instead of passing the name of the method to be invoked as the first method argument.

Here’s a diagram I used in DDC 2012 that illustrates the process mentioned above:

For this example, we will have an application that hosts a HTML5 page that displays memory information of the device (as shown in the screenshot below)

And here’s the code…

Default.html (HTML5 + Javascript)

The code below is going to be used as a local html file that is to be copied to isolated storage. Let’s put this in a folder called HTML

<!DOCTYPE html>
<html>
<head>
    <meta name=”viewport” content=”width=480, height=800, user-scalable=no” />
    <meta name=”MobileOptimized” content=”width” />
    <meta name=”HandheldFriendly” content=”true” />
    <title>HTML5 and Windows Phone 7</title>
    <style>
        body
        {
            color: White;
            background-color: Black;
            font-family: ‘Segoe WP Semibold’;
            text-align: left;
        }
        h3
        {
            font-size: 20pt;
        }
        input
        {
            color: #ffffff;
            background-color: #000000;
            border: 2px solid white;
            vertical-align: baseline;
            font-size: 17pt;
            min-width: 40px;
            min-height: 40px;
            margin: 5;
        }
    </style>
</head>
<body onload=”onLoad()”>
    <div>
        <h3>
            Current memory usage:</h3>
        <input id=”memoryUsage” type=”text” value=”0″ />
        <h3>
            Memory usage limit:</h3>
        <input id=”memoryUsageLimit” type=”text” value=”0″ />
        <h3>
            Peak memory usage:</h3>
        <input id=”peakMemoryUsage” type=”text” value=”0″ />
        <h3>
            Total memory:</h3>
        <input id=”totalMemory” type=”text” value=”0″ />
    </div>
    <script type=”text/javascript”>
        function onLoad() {
            window.external.notify(“getMemoryUsage”);
        }
        function getMemoryUsageCallback(memoryUsage, memoryUsageLimit, peakMemoryUsage, totalMemory) {
            document.getElementById(“memoryUsage”).value = memoryUsage;
            document.getElementById(“memoryUsageLimit”).value = memoryUsageLimit;
            document.getElementById(“peakMemoryUsage”).value = peakMemoryUsage;
            document.getElementById(“totalMemory”).value = totalMemory;
        }
    </script>
</body>
</html>

MainPage.xaml

The code below is the main page of the Silverlight application that will host the HTML content

<phone:PhoneApplicationPage x:Class=”PhoneApp.MainPage”
                           xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
                           xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
                           xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
                           xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
                           xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
                           xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
                           mc:Ignorable=”d”
                           d:DesignWidth=”480″
                           d:DesignHeight=”768″
                           FontFamily=”{StaticResource PhoneFontFamilyNormal}”
                           FontSize=”{StaticResource PhoneFontSizeNormal}”
                           Foreground=”{StaticResource PhoneForegroundBrush}”
                           SupportedOrientations=”Portrait”
                           Orientation=”Portrait”
                           shell:SystemTray.IsVisible=”True”
                           Loaded=”PhoneApplicationPage_Loaded”>
    <Grid x:Name=”LayoutRoot”
         Background=”Transparent”>
        <phone:WebBrowser Name=”browser”
                         IsScriptEnabled=”True”
                         Source=”HTML/Default.html”
                         ScriptNotify=”browser_ScriptNotify” />
    </Grid>
</phone:PhoneApplicationPage>

MainPage.xaml.cs

And here’s the code behind the xaml file

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
    }
    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (!store.DirectoryExists(“HTML”)) store.CreateDirectory(“HTML”);
            CopyToIsolatedStorage(“HTML\Default.html”, store);
        }
    }
    private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true)
    {
        if (store.FileExists(file) && !overwrite)
            return;
        using (Stream resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream)
        using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            int bytesRead;
            var buffer = new byte[resourceStream.Length];
            while ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)
                fileStream.Write(buffer, 0, bytesRead);
        }
    }
    private void browser_ScriptNotify(object sender, NotifyEventArgs e)
    {
        var response = new object[]
                       {
                           DeviceStatus.ApplicationCurrentMemoryUsage,
                           DeviceStatus.ApplicationMemoryUsageLimit,
                           DeviceStatus.ApplicationPeakMemoryUsage,
                           DeviceStatus.DeviceTotalMemory
                       };
        browser.InvokeScript(“getMemoryUsageCallback”, response.Select(c => c.ToString()).ToArray());
    }
}

What happens in the code above is that when the main page has loaded, the html assets are copied to isolated storage and loaded into the web browser component as a local file. When ScriptNotify is triggered, the Silverlight application retrieves memory information using the DeviceStatus class and passes this information back to the WebBrowser component by invoking the getMemoryUsageCallback() method using the InvokeScript() method of the WebBrowser component

The sample above is a very basic and naive but it demonstrates something that can provide endless platform interop possibilities. I hope you found this useful.

You can grab the full source code the sample above here:

HTML5 and Windows Phone 7

Last week I did a talk on HTML5 and Windows Phone for the Danish Developer Conference 2012. The talk was quite successful and around 80% of said that they learned something new, which is the whole point of these conferences.

If you’re interested in my presentation and code examples then you can download it at http://dl.dropbox.com/u/18352048/Presentations/Windows%20Phone%20and%20HTML5/Windows%20Phone%20and%20HTML5.rar