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 then you can download it from here and code examples from here



Danish Developer Conference 2012

There’s a lot of talks about HTML5 these days and I myself will be doing a talk regarding the subject in the Danish Developer Conference. I was planning on saving my content for my presentation but once my talk is done I’ll be posting a couple of articles on HTML5 and Windows Phone 7.

Here’s an introduction / teaser to what I’ll be presenting…



A long break...

As I come back from another long blogging break, a lot of great things have happened in my life…

The greatest experience I’ve had so far in my life was on September 15, 2011 I became a father to this wonderfully charming little guy you see below:

I took a full month off work to play daddy and to assist my wife with everything I possibly can. It was a great time and I’ll never regret or forget that.

My hands were completely tied from work the day I got back from my leave. Luckily the projects were all very exciting and challenging, but did require me to spend a ton of hours on work. I had the chance to work on an online music service called TDC Play for a rather large danish based telecom company called TDC. I unfortunately only took part in the design and development of the Windows Phone 7 version, but the app is also available on the iOS and Android.

The app was extremely fun to make and I got the to work with my old colleages from the Microsoft Development Center in Copenhagen. I expect to post some articles on performance, background agents, Implementing a MediaStreamSource for streaming or progressive downloads, and loads of other fun stuff.

I also got started again in doing some speaking events. In February 29 in Horsons, Denmark I’ll be doing a talk on Windows Phone 7 and HTML5 for the Danish Developer Conference and on February 13 I’ll be doing an online talk on Background Agents on Windows Phone 7

So what’s next for me in the blogsphere? Well to begin with I’d like to continue on my series Multi-platform Mobile Development and some articles on Windows Phone 7 development. I’m looking forward to getting back into writing some useful articles.

I’ll probably also be back on the MSDN forums, especially the Smart Device section to help out other developers running into issues with mobile development



SQL Compact Query Analyzer

I’ve been working extensively on enterprise mobility projects lately. These applications integrate into large SAP based systems and when testing the system it can get very tedious to set up some temporary data from the backend. I’m also working with some not-so-technical testers that get intimidated by the Visual Studio or the SQL Server Management Studio. This led me to writing an open source project called SQL Compact Query Analyzer

Here’s some details I pulled directly off the CodePlex Github page

Project Description

A SQL Server Compact Edition Database Query Analyzer

Download latest release here

Features:

  • Create new database
  • Automatically refresh database upon executing create/alter/drop table queries
  • Displays database information (database version, filename, size, creation date)
  • Displays schema summary (number of tables, columns, primary keys, identity fields, nullable fields)
  • Displays the information schema views
  • Displays column information (database type, clr type, max length, allows null, etc)
  • Displays index information (column name, is unique, is clustered)
  • Execute SQL Queries against a SQL Server Compact Edition database
  • Execute multiple SQL queries (delimited by a semi colon ;)
  • Easily edit the contents of the database
  • Display query result as XML
  • Shrink and Compact Databases
  • SDF file association with SQL Compact Query Analyzer for launching directly by opening the SDF in Windows Explorer
  • Displays thumbnails for IMAGE fields
  • Generates Schema and Data Scripts
  • Supports password protected databases
  • Supports SQLCE 3.0, 3.1, 3.5 and 4.0

Coming at some point:

  • Purge database content
  • Create, edit, and drop tables UI
  • Create, edit, and delete table references and indexes UI
  • Support for SQL Server Compact Edition 2.0

Screenshots

alt text

  • Displays database and schema information and executes multiple SQL queries directly

alt text

  • Edit the table data directly

alt text

  • Display the contents of IMAGE fields

alt text

  • Performance numbers for queries

alt text

  • Query errors

alt text

  • Output result set as XML

alt text

  • Create new database

alt text

  • Shrink, compact, script database

Prerequisites:

  • .NET Framework 4.0

Check it out! You might find it useful!