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:

Working around Pivot SelectedIndex limitations in Windows Phone 7

I’ve been working on an application with 2 pages, a main page and a content page. The content page contains a Pivot control with a few pivot items. The main page does nothing but navigate to the content page and suggest which pivot item to display. The only reason the main page exists is to display the information in the pivot item headers in a more graphical and elegant way.

For some reason I can’t set the displayed pivot index to be the third item. I wanted to do this on the OnNavigatedTo event of the content page but whenever I attempt doing so an exception is thrown. Every other pivot item works fine, which I think is really weird.

To load the content page, I navigate to the page by passing some information of the pivot index I wish to be displayed. Something like this:

NavigationService.Navigate(new Uri("/ContentPage.xaml?index=" + index, UriKind.Relative));

If the value of index in the code above is set to 2 then I get an exception, any other valid value works fine. A value out of range (less than 0 or greater than 5) throws an out of range exception which is the behavior anyone would expect.

Here’s the XAML definition of the content page

<phone:PhoneApplicationPage
    x:Class="WindowsPhonePivotApplication.ContentPage"
    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:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
    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">
 
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <controls:Pivot Name="pivot" Title="CONTENT PAGE">
      <controls:PivotItem Header="first" />
      <controls:PivotItem Header="second" />
      <controls:PivotItem Header="third" />
      <controls:PivotItem Header="fourth" />
      <controls:PivotItem Header="fifth" />
      <controls:PivotItem Header="sixth" />
    </controls:Pivot>
  </Grid>
 
</phone:PhoneApplicationPage>

To work around this limitation, you can handle the Loaded event of the page and update the pivot selected index from there. Here’s an example how to do it:

public partial class ContentPage : PhoneApplicationPage
{
    private int pivotIndex;
 
    public ContentPage()
    {
        InitializeComponent();
 
        Loaded += delegate { pivot.SelectedIndex = pivotIndex; };
    }
 
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        string value;
        if (NavigationContext.QueryString.TryGetValue("index", out value))
        {
            pivotIndex = 0;
            int.TryParse(value, out pivotIndex);
        }
    }
}

I’m not sure if this limitation is by design or it’s a bug in the control. Either way I managed to get it to work the way I wanted it to. Hopefully I’m not the only one who ran across this and that you found this information useful.

Multi-platform Mobile Development – Sending SMS

This is a task that pretty much every mobile device can do, or at least any mobile phone can do. In this short post on multi-platform mobile development I would like to demonstrate how to send an SMS or launch the SMS compose window in a mobile application.

I’m going to demonstrate how to use the messaging API’s of the following platforms:

  • Android
  • Windows Phone 7
  • Windows Mobile 5.0 (and higher) using .NET Compact Framework
  • Windows Mobile using the Platform SDK (Native code)

Android

There are 2 ways of sending SMS from an Android application: Launching the Compose SMS window; Through the SmsManager API. I figured that since this article is supposed to demonstrate as many ways as possible for sending SMS that I create a helper class containing methods that I think would be useful or at least convenient to have.

Here’s a SMS helper class for Android that I hope you would find useful.

package com.christianhelle.android.samples;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.telephony.SmsManager;
import android.widget.Toast;

/**
* Helper class for sending SMS messages
*
*
@author Christian Resma Helle
*/
public class Sms {
   
private final static String SENT_ACTION = "SENT";
   
private final static String DELIVERED_ACTION = "DELIVERED";
   
private Context context;
   
private PendingIntent sentIntent;
   
private PendingIntent deliveredIntent;

    /**
     * Creates an instance of the SMS class
     *
     *
@param context     Context that owns displayed notifications
     */
   
public Sms(Context context) {
       
this.context = context;
        registerForNotification
();
   
}

    private void registerForNotification() {
       
sentIntent = PendingIntent.getBroadcast(context, 0, new Intent(SENT_ACTION), 0);
        deliveredIntent = PendingIntent.getBroadcast
(context, 0, new Intent(DELIVERED_ACTION), 0);

        context.registerReceiver(messageSentReceiver, new IntentFilter(SENT_ACTION));
        context.registerReceiver
(messageDeliveredReceiver, new IntentFilter(DELIVERED_ACTION));
   
}
    
   
protected void finalize() throws Throwable {
       
context.unregisterReceiver(messageSentReceiver);
        context.unregisterReceiver
(messageDeliveredReceiver);
   
}

    /**
     * Opens the Compose SMS application with the recipient phone number displayed
     *
     *
@param phoneNumber     recipient phone number of the SMS
     */
   
public void composeMessage(String phoneNumber) {
       
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("sms:" + phoneNumber));
        context.startActivity
(intent);
   
}

    /**
     * Opens the Compose SMS application with the recipient phone number and message displayed
     *
     *
@param phoneNumber     recipient phone number of the SMS
     *
@param text             message body
     */
   
public void composeMessage(String phoneNumber, String text) {
       
Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.putExtra
("sms_body", text);
        intent.putExtra
("address", phoneNumber);
        intent.setType
("vnd.android-dir/mms-sms");
        context.startActivity
(intent);
   
}

    /**
     * Opens the Compose SMS application with the multiple recipient phone numbers and the message displayed
     *
     *
@param phoneNumber     recipient phone numbers of the SMS
     *
@param text             message body
     */
   
public void composeMessage(String[] phoneNumbers, String text) {
       
StringBuilder sb = new StringBuilder();
       
for (String string : phoneNumbers) {
           
sb.append(string);
            sb.append
(";");
       
}
       
composeMessage(sb.toString(), text);
   
}

    /**
     * Send an SMS to the specified number
     *
     *
@param phoneNumber     recipient phone number of the SMS
     *
@param text             message body
     */
   
public void sendMessage(String phoneNumber, String text) {
       
sendMessage(phoneNumber, text, false);
   
}

    /**
     * Send an SMS to the specified number and display a notification on the message status
     * if the notifyStatus parameter is set to
<b>true</b>
    
*
     *
@param phoneNumber     recipient phone number of the SMS
     *
@param text             message body
     *
@param notifyStatus     set to <b>true</b> to display a notification on the screen
     *                         if the message was sent and delivered properly, otherwise
<b>false</b>
    
*/
   
public void sendMessage(String phoneNumber, String text, boolean notifyStatus) {
       
SmsManager sms = SmsManager.getDefault();
       
if (notifyStatus) {
           
sms.sendTextMessage(phoneNumber, null, text, sentIntent, deliveredIntent);   
       
} else {
           
sms.sendTextMessage(phoneNumber, null, text, null, null);
       
}   
    }

    /**
     * Send an SMS to multiple recipients and display
     *
     *
@param phoneNumber     recipient phone number of the SMS
     *
@param text             message body
     */
   
public void sendMessage(String[] phoneNumbers, String text) {
       
sendMessage(phoneNumbers, text, false);
   
}

    /**
     * Send an SMS to multiple recipients and display a notification
     * on the message status if notifyStatus is set to
<b>true</b>
    
*
     *
@param phoneNumber     recipient phone number of the SMS
     *
@param text             message body
     *
@param notifyStatus     set to <b>true</b> to display a notification on the screen
     *                         if the message was sent and delivered properly, otherwise
<b>false</b>
    
*/
   
public void sendMessage(String[] phoneNumbers, String text, boolean notifyStatus) {
       
StringBuilder sb = new StringBuilder();
       
for (String string : phoneNumbers) {
           
sb.append(string);
            sb.append
(";");
       
}
       
sendMessage(sb.toString(), text, notifyStatus);
   
}

    private BroadcastReceiver messageSentReceiver = new BroadcastReceiver() {
       
@Override
       
public void onReceive(Context context, Intent intent) {
           
switch (getResultCode()) {
           
case Activity.RESULT_OK:
                Toast.makeText
(context, "SMS sent", Toast.LENGTH_SHORT).show();
               
break;
           
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                Toast.makeText
(context, "Generic failure", Toast.LENGTH_SHORT).show();
               
break;
           
case SmsManager.RESULT_ERROR_NO_SERVICE:
                Toast.makeText
(context, "No service", Toast.LENGTH_SHORT).show();
               
break;
           
case SmsManager.RESULT_ERROR_NULL_PDU:
                Toast.makeText
(context, "Null PDU", Toast.LENGTH_SHORT).show();
               
break;
           
case SmsManager.RESULT_ERROR_RADIO_OFF:
                Toast.makeText
(context, "Radio off", Toast.LENGTH_SHORT).show();
               
break;
           
}
        }
    }
;

    private BroadcastReceiver messageDeliveredReceiver = new BroadcastReceiver() {
       
@Override
       
public void onReceive(Context context, Intent intent) {
           
switch (getResultCode()) {
           
case Activity.RESULT_OK:
                Toast.makeText
(context, "Message delivered", Toast.LENGTH_SHORT).show();
               
break;
           
case Activity.RESULT_CANCELED:
                Toast.makeText
(context, "Message not delivered", Toast.LENGTH_SHORT).show();
               
break;
           
}
        }
    }
;
}

Before your Android application can send SMS it needs the right permissions for it. Add the SEND_SMS permission your AndroidManifest.xml

<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>

Here are some examples on how to use the SMS helper class defined above from within an Activity class:

Sms sms = new Sms(getApplicationContext());

// Send an SMS to the specified number
sms.sendMessage("+4512345678", "Multi-platform Mobile Development");

// Send an SMS to the specified number and display a notification on the message status
sms.sendMessage("+4512345678", "Multi-platform Mobile Development", true);

// Send an SMS to multiple recipients
sms.sendMessage(new String[] { "+4512345678", "+4598765432" }, "Multi-platform Mobile Development");       

// Send an SMS to multiple recipients and display a notification on the message status
sms.sendMessage(new String[] { "+4512345678", "+4598765432" }, "Multi-platform Mobile Development", true);

// Opens the Compose SMS application with the recipient phone number displayed
sms.composeMessage("+4512345678");

// Opens the Compose SMS application with the recipient phone number and message displayed
sms.composeMessage("+4512345678", "Multi-platform Mobile Development");

// Opens the Compose SMS application with the multiple recipient phone numbers and the message displayed
sms.composeMessage(new String[] { "+4512345678", "+4598765432" }, "Multi-platform Mobile Development");

Windows Phone 7

This platform unfortunately doesn’t provide as vast a API collection compared to Android and Windows Mobile. To send an SMS in Windows Phone 7, you will have to use the SMS Compose page in the built-in messaging application. To launch this we call the Show() method in SmsComposeTask.

Here’s how to use SmsComposeTask

SmsComposeTask launcher = new SmsComposeTask();
launcher.To = "+45 12 34 56 78";
launcher.Body = "Multi-platform Mobile Development";
launcher.Show();

Windows Mobile 5.0 (and higher) using .NET Compact Framework

Sending an SMS in this platform is just as easy as doing so in Windows Phone 7. Windows Mobile provides native API’s for the Short Messaging System, these methods are exposed as C type methods in a DLL called sms.dll. Aside from the SMS API, the platform also offers another API called the Messaging API (CE MAPI) for sending SMS, MMS, and Emails. Microsoft has provided managed wrappers for these and many other API’s to make the life of the managed code developer a lot easier.

To send an SMS in Windows Mobile 5.0 (and higher) we use the SmsMessage object. There are 2 ways of accomplishing this: Using the Send() method of the SmsMessage class; Sending the SMS using the Compose SMS application

Here’s a snippet on how to send SMS using the Send() method

SmsMessage sms = new SmsMessage("+45 12 34 56 78", "Multi-platform Mobile Development");
sms.Send();

Here’s a snippet on how to send SMS using the Compose SMS application

SmsMessage sms = new SmsMessage("+45 12 34 56 78", "Multi-platform Mobile Development");
MessagingApplication.DisplayComposeForm(sms);

The code above depends on 2 assemblies that must be referenced to the project:

  • Microsoft.WindowsMobile.dll
  • Microsoft.WindowsMobile.PocketOutlook.dll

It is also possible to P/Invoke the SMS API through sms.dll, but this requires a slightly more complicated solution. In the next section, I will demonstrate how use the SMS API in native code. This should give you an idea on how to use the SMS API if you would like to go try the P/Invoke approach.

Windows Mobile using the Platform SDK (Native code)

Probably not very relevant for most modern day managed code developers but just to demonstrate as many ways to send SMS in as many platforms as possible I’d like to show how to send SMS in native code using the Windows CE Short Message Service (SMS) API.

Here’s a sample C++ helper class for sending SMS using the Platform SDK

#include "stdafx.h"
#include "sms.h"
#include <string>
 
class SmsMessage 
{
private:
    std::wstring recipient;
    std::wstring message;
 
public:
    SmsMessage(const wchar_t* phoneNumber, const wchar_t* text) 
    {
        recipient = phoneNumber;
        message = text;
    }
 
    void Send() 
    {
        SMS_HANDLE smshHandle;
        HRESULT hr = SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL);
        if (hr != S_OK)
            return;
 
        SMS_ADDRESS smsaDestination;
        memset (&smsaDestination, 0, sizeof (smsaDestination));
        smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL;
        lstrcpy(smsaDestination.ptsAddress, recipient.c_str());
 
        TEXT_PROVIDER_SPECIFIC_DATA tpsd;
        tpsd.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
        tpsd.psMessageClass = PS_MESSAGE_CLASS1;
        tpsd.psReplaceOption = PSRO_NONE;
 
        SMS_MESSAGE_ID smsmidMessageID = 0;
        hr = SmsSendMessage(smshHandle, 
                            NULL, 
                            &smsaDestination, 
                            NULL,
                            (PBYTE) message.c_str(), 
                            (message.length() + 1) * sizeof(wchar_t), 
                            (PBYTE) &tpsd, 
                            sizeof(TEXT_PROVIDER_SPECIFIC_DATA), 
                            SMSDE_OPTIMAL, 
                            SMS_OPTION_DELIVERY_NONE, 
                            &smsmidMessageID);
 
        SmsClose (smshHandle);
    }
};

The code above requires the that the project is linked with sms.lib, otherwise you won’t be able to build.

Here’s a snippet of how to use the SMS helper class defined above:

SmsMessage *sms = new SmsMessage(L"+14250010001", L"Multi-platform Mobile Development");
sms->Send();
delete sms;

For those who don’t know what +14250010001 is, this is the phone number of the Windows Mobile emulator. For testing SMS functionality on the emulator, you can use this phone number.

That’s it for now. I hope you found this article interesting.

Multi-platform Mobile Development – Creating a List Based UI

Here’s the first installment on my series on multi-platform mobile development articles. A common practice on displaying information to a mobile device user is a list. A list is one of the best ways to display a group of information allowing the user to easily select which specific details he/she wishes to display.

A good example of decent list implementations is the Inbox on pretty much all mobile devices. Most Inbox list implementations display sender, title, date, size, and a preview of the message body. A good list is not only bound to textual information but also visual. Most Inbox implementation displays the information using bold fonts if the message is unread

In this article I would like to demonstrate how to implement customized list based UI’s on the following platforms:

  1. Windows Phone 7
  2. Windows Mobile using .NET Compact Framework
  3. Android

Let’s get started…

Windows Phone 7

This is definitely the easiest platform to target, in fact this is by far the easiest platform I’ve ever worked with. Development times on this platform are a lot shorter than any other platform I’ve worked with. I’ve been working with Windows CE based phones for the last 7 or so and I definitely think that this is the best Windows CE based OS ever. There unfortunately a few down sides like lack of a native code API and limited platform integration, but considering the performance and development ease, it is for most cases worth it. The best part with designing UI’s for Windows Phone 7 is that I don’t have to care about the design very much, I just ask my designer / graphic artist to shine up my XAML file and I can concentrate on the code.

A Visual Studio 2010 project template is actually provided by default for creating a list based UI makes things easier. This project template is called a Windows Phone Databound Applicaton, the description goes “A project for creating Windows Phone applications using List and Navigation controls”. This project creates 2 pages, one for displaying the list, and the other for displaying details of this list.

The code examples for Windows Phone 7 uses the Model-View-ViewModel. This pattern is heavily used and I guess one can say an accepted standard in developing Windows Phone 7 applications. I’m not gonna go deep into the pattern in this article, so I assume that you do a bit of home work on MVVM.

To display a list Windows Phone 7 we use the ListBox control in XAML. This will represent the View.

<ListBox ItemsSource="{Binding Items}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel>
        <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap"/>
        <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap"/>
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Our ViewModel is implemented in code. A ViewModel class should implement the INotifyPropertyChanged interface for the View to be able to respond to changes in the ViewModel.

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
 
public class ItemViewModel : ViewModelBase
{
    private string _lineOne;
    public string LineOne
    {
        get { return _lineOne; }
        set
        {
            if (value != _lineOne)
            {
                _lineOne = value;
                NotifyPropertyChanged("LineOne");
            }
        }
    }
 
    private string _lineTwo;
    public string LineTwo
    {
        get { return _lineTwo; }
        set
        {
            if (value != _lineTwo)
            {
                _lineTwo = value;
                NotifyPropertyChanged("LineTwo");
            }
        }
    }
}
 
public class MainViewModel : ViewModelBase
{
    private MainModel model;
 
    public MainViewModel()
    {
        model = new MainModel();
        Items = model.GetData();
    }
 
    public ObservableCollection<ItemViewModel> Items { get; private set; }
}

The ViewModel code above contains an instance of the Model. The Model in this naive example just returns a populated collection of ItemViewModel.

public class MainModel
{
    public ObservableCollection<ItemViewModel> GetData()
    {
        return new ObservableCollection<ItemViewModel> 
        {
            new ItemViewModel() { LineOne = "runtime one", LineTwo = "Maecenas praesent accumsan bibendum" },
            new ItemViewModel() { LineOne = "runtime two", LineTwo = "Dictumst eleifend facilisi faucibus" },
            new ItemViewModel() { LineOne = "runtime three", LineTwo = "Habitant inceptos interdum lobortis" },
            new ItemViewModel() { LineOne = "runtime four", LineTwo = "Nascetur pharetra placerat pulvinar" }
        };
    }
}

Here’s how the application looks like:

Windows Mobile

This is actually a pretty decent platform and offers a huge selection of low level API’s for platform integration. The OS also offers full multi tasking and the ability to create applications that run behind scenes. The down side of course to all that fun stuff is that you have to do a lot of things the hard way. Implementing a decent list based UI in this platforms can be done in 2 ways: Using the Windows CE custom drawing service; Creating an Owner Drawn List Control. Both require writing a few hundred lines of code.

For this example we create an Owner Drawn List. For those who are not familiar what that means, we draw the entire control from scratch, manually. We create a class that inherits from System.Windows.Forms.Control (the base class of all UI components) and override the drawing, resizing, and input methods. It’s a bit tedious, but most of the code in owner drawn controls can be re-used as base classes for other owner drawn controls.

Let’s start off with creating an owner drawn list base class.

abstract class OwnerDrawnListBase<T> : Control
{
    int selectedIndex;
    int visibleItemsPortrait;
    int visibleItemsLandscape;
    VScrollBar scrollBar;
 
    protected OwnerDrawnListBase()
        : this(7, 4)
    {
    }
 
    protected OwnerDrawnListBase(int visibleItemsPortrait, int visibleItemsLandscape)
    {
        this.visibleItemsPortrait = visibleItemsPortrait;
        this.visibleItemsLandscape = visibleItemsLandscape;
 
        Items = new List<T>();
 
        scrollBar = new VScrollBar { Parent = this, Visible = false, SmallChange = 1 };
        scrollBar.ValueChanged += (sender, e) => Invalidate();
    }
 
    public List<T> Items { get; private set; }
 
    public int SelectedIndex
    {
        get { return selectedIndex; }
        set
        {
            selectedIndex = value;
            if (SelectedIndexChanged != null)
                SelectedIndexChanged(this, EventArgs.Empty);
            Invalidate();
        }
    }
 
    public event EventHandler SelectedIndexChanged;
 
    protected virtual void OnSelectedIndexChanged(EventArgs e)
    {
        if (SelectedIndexChanged != null)
            SelectedIndexChanged(this, e);
    }
 
    public T SelectedItem
    {
        get
        {
            if (selectedIndex >= 0 && selectedIndex < Items.Count)
                return Items[selectedIndex];
            else
                return null;
        }
    }
 
    protected Bitmap OffScreen { get; private set; }
 
    protected int VisibleItems
    {
        get
        {
            if (Screen.PrimaryScreen.Bounds.Height > Screen.PrimaryScreen.Bounds.Width)
                return visibleItemsPortrait;
            else
                return visibleItemsLandscape;
        }
    }
 
    protected int ItemHeight
    {
        get { return Height / VisibleItems; }
    }
 
    protected int ScrollPosition
    {
        get { return scrollBar.Value; }
    }
 
    protected bool ScrollBarVisible
    {
        get { return scrollBar.Visible; }
    }
 
    protected int ScrollBarWidth
    {
        get { return scrollBar.Width; }
    }
 
    protected int DrawCount
    {
        get
        {
            if (ScrollPosition + scrollBar.LargeChange > scrollBar.Maximum)
                return scrollBar.Maximum - ScrollPosition + 1;
            else
                return scrollBar.LargeChange;
        }
    }
 
    #region Overrides
 
    protected override void OnResize(EventArgs e)
    {
        scrollBar.Bounds = new Rectangle(
            ClientSize.Width - scrollBar.Width,
            0,
            scrollBar.Width,
            ClientSize.Height);
 
        Dispose(OffScreen);
 
        if (Items.Count > VisibleItems)
        {
            scrollBar.Visible = true;
            scrollBar.LargeChange = VisibleItems;
            OffScreen = new Bitmap(ClientSize.Width - scrollBar.Width, ClientSize.Height);
        }
        else
        {
            scrollBar.Visible = false;
            scrollBar.LargeChange = Items.Count;
            OffScreen = new Bitmap(ClientSize.Width, ClientSize.Height);
        }
        DrawBorder();
 
        scrollBar.Maximum = Items.Count - 1;
    }
 
    private void DrawBorder()
    {
        using (var gfx = Graphics.FromImage(OffScreen))
        using (var pen = new Pen(SystemColors.ControlText))
            gfx.DrawRectangle(pen, new Rectangle(0, 0, OffScreen.Width - 1, OffScreen.Height - 1));
    }
 
    protected override void OnMouseDown(MouseEventArgs e)
    {
        // Update the selected index based on where the user clicks
        SelectedIndex = scrollBar.Value + (e.Y / ItemHeight);
        if (SelectedIndex > Items.Count - 1)
            SelectedIndex = -1;
 
        if (!Focused)
            Focus();
 
        base.OnMouseUp(e);
    }
 
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // To avoid flickering, do all drawing in OnPaint
    }
 
    protected override void Dispose(bool disposing)
    {
        if (disposing)
            Dispose(OffScreen);
        base.Dispose(disposing);
    }
 
    #endregion
 
    protected static void Dispose(IDisposable obj)
    {
        if (obj != null)
        {
            obj.Dispose();
            obj = null;
        }
    }
}

The class above implements the basic functionality of an owner drawn list. It hands resizing the off screen bitmap that serves as a double buffer, handles the scroll bar visibility, and handles updating the selected index. One can implement responding to keyboard input or gestures from here as well.

Next we create a class where we define how the control is drawn. This class inherits from our owner drawn list base class.

class CustomListViewItem
{
    public string LineOne { get; set; }
    public string LineTwo { get; set; }
}
 
class CustomListView : OwnerDrawnListBase<CustomListViewItem>
{
    const int topleft = 3;
 
    StringFormat noWrap;
    Pen pen;
    SolidBrush backgroundBrush;
    SolidBrush selectedBrush;
    SolidBrush selectedTextBrush;
    SolidBrush textBrush;
    Font headerFont;
 
    public override Font Font
    {
        get { return base.Font; }
        set
        {
            base.Font = value;
            Dispose(headerFont);
            headerFont = new Font(value.Name, value.Size, FontStyle.Bold);
        }
    }
 
    public CustomListView()
    {
        pen = new Pen(ForeColor);
        textBrush = new SolidBrush(ForeColor);
        backgroundBrush = new SolidBrush(BackColor);
        selectedTextBrush = new SolidBrush(SystemColors.HighlightText);
        selectedBrush = new SolidBrush(SystemColors.Highlight);
        noWrap = new StringFormat(StringFormatFlags.NoWrap);
        headerFont = new Font(base.Font.Name, base.Font.Size, FontStyle.Bold);
    }
 
    protected override void OnPaint(PaintEventArgs e)
    {
        using (var gfx = Graphics.FromImage(OffScreen))
        {
            gfx.FillRectangle(backgroundBrush, 1, 1, Width - 2, Height - 2);
 
            int top = 1;
            bool lastItem = false;
            bool itemSelected = false; ;
 
            for (var i = ScrollPosition; i < ScrollPosition + DrawCount; i++)
            {
                if (top > 1)
                    lastItem = Height - 1 < top;
 
                // Fill the rectangle if the item is selected
                itemSelected = i == SelectedIndex;
                if (itemSelected)
                {
                    if (!lastItem)
                    {
                        gfx.FillRectangle(
                            selectedBrush,
                            1,
                            (i == ScrollPosition) ? top : top + 1,
                            ClientSize.Width - (ScrollBarVisible ? ScrollBarWidth : 2),
                            (i == ScrollPosition) ? ItemHeight : ItemHeight - 1);
                    }
                    else
                    {
                        gfx.FillRectangle(
                            selectedBrush,
                            1,
                            top + 1,
                            ClientSize.Width - (ScrollBarVisible ? ScrollBarWidth : 1),
                            ItemHeight);
                    }
                }
 
                // Draw seperator lines after each item unless the item is the last item in the list
                if (!lastItem)
                {
                    gfx.DrawLine(
                        pen,
                        1,
                        top + ItemHeight,
                        ClientSize.Width - (ScrollBarVisible ? ScrollBarWidth : 2),
                        top + ItemHeight);
                }
 
                // Get the dimensions for creating the drawing areas
                var item = Items[i];
                var size = gfx.MeasureString(item.LineOne, Font);
                var rectheight = ItemHeight - (int)size.Height - 6;
                var rectwidth = ClientSize.Width - (ScrollBarVisible ? ScrollBarWidth : 5);
 
                // Draw line one with an offset of 3 pixels from the top of the rectangle 
                // using a bold font (no text wrapping)
                gfx.DrawString(
                    item.LineOne,
                    headerFont,
                    (i == SelectedIndex) ? selectedTextBrush : textBrush,
                    new RectangleF(topleft, top + 3, rectwidth, rectheight),
                    noWrap);
 
                // Draw line two with an offset of 3 pixels from the bottom of line one 
                // (no text wrapping)
                gfx.DrawString(
                    item.LineTwo,
                    Font,
                    (i == SelectedIndex) ? selectedTextBrush : textBrush,
                    new RectangleF(topleft, top + size.Height + 6, rectwidth, rectheight),
                    noWrap);
 
                // Set the top for the next item
                top += ItemHeight;
            }
 
            e.Graphics.DrawImage(OffScreen, 0, 0);
        }
    }
 
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            Dispose(headerFont);
            Dispose(backgroundBrush);
            Dispose(textBrush);
            Dispose(selectedTextBrush);
            Dispose(selectedBrush);
            Dispose(pen);
        }
 
        base.Dispose(disposing);
    }
}

Once that is in place you can just drag it in from the toolbox or dynamically add it to the Form in runtime.

var lv = new CustomListView();
lv.Dock = DockStyle.Fill;
Controls.Add(lv);
 
lv.Items.AddRange(new List<CustomListViewItem>
{
    new CustomListViewItem { LineOne = "runtime one", LineTwo = "Maecenas praesent accumsan bibendum" },
    new CustomListViewItem { LineOne = "runtime two", LineTwo = "Dictumst eleifend facilisi faucibus" },
    new CustomListViewItem { LineOne = "runtime three", LineTwo="Habitant inceptos interdum lobortis" },
    new CustomListViewItem { LineOne = "runtime four", LineTwo="Nascetur pharetra placerat pulvinar" },
    new CustomListViewItem { LineOne = "runtime five", LineTwo = "Maecenas praesent accumsan bibendum" },
    new CustomListViewItem { LineOne = "runtime six", LineTwo = "Dictumst eleifend facilisi faucibus" },
    new CustomListViewItem { LineOne = "runtime seven", LineTwo="Habitant inceptos interdum lobortis" },
    new CustomListViewItem { LineOne = "runtime eight", LineTwo="Nascetur pharetra placerat pulvinar" }
});

Here’s how the custom list view looks like in a Windows Mobile 6.5.3 emulator

You can grab the source for Windows Mobile application above here.

Android

Creating decent list based UI’s is also pretty easy. The designer experience is unfortunately not as elegant as what Windows Phone 7 has to offer, but shares the same idea. The user interface layout of Android applications are described in XML files and are parsed during runtime. In some occasions it seems easier to create the UI layout in runtime through code instead of struggling with the UI designer. This is probably because of my lack of patience with the tool or because of my lack of experience using it. Either way, I think it could have been done in a much smarter way.

To create a list based UI in Android we can create a class that extends from the ListActivity class. The ListActivity base class contains a List control set to fill the parent, it comes in handy if you want a UI with nothing but a list control. In android development, you usually setup the UI and do other initialization methods in the onCreate() method, our example will do the same. We set the data source of our list control by calling setListAdapter().

To have a more flexible and customizable we use the ArrayAdapter for presenting our data source to the screen. To optimize performance, we use an object called convertView that ArrayAdapter exposes, we can store a single instance of a class containing UI text components and just update the text for that instance. This is done by overriding the ArrayAdapter getView method.

Here’s the code for implementing the ListActivity and ArrayAdapter

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class MainActivity extends ListActivity {
   
@Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setListAdapter
(new ListItemActivity(this, R.layout.list_item, createList()));
   
}

    private List<ListItem> createList() {
       
List<ListItem> list = new ArrayList<ListItem>();
        list.add
(new ListItem("runtime one", "Maecenas praesent accumsan bibendum"));
        list.add
(new ListItem("runtime two", "Dictumst eleifend facilisi faucibus"));
        list.add
(new ListItem("runtime three", "Habitant inceptos interdum lobortis"));
        list.add
(new ListItem("runtime four", "Nascetur pharetra placerat pulvinar"));
       
return list;
   
}

    class ListItem {
       
public String lineOne;
       
public String lineTwo;

        public ListItem(String lineOne, String lineTwo) {
           
this.lineOne = lineOne;
           
this.lineTwo = lineTwo;
       
}
    }

    class ListItemActivity extends ArrayAdapter<ListItem> {
       
private Activity context;
       
private List<ListItem> items;

        public ListItemActivity(Activity context, int textViewResourceId, List<ListItem> items) {
           
super(context, textViewResourceId, items);
           
this.context = context;
           
this.items = items;
       
}

        @Override
       
public View getView(int position, View convertView, ViewGroup parent) {
           
ViewHolder holder;
           
if (convertView == null) {
               
LayoutInflater inflater = context.getLayoutInflater();
                convertView = inflater.inflate
(R.layout.list_item, parent, false);
                holder =
new ViewHolder();
                holder.lineOne =
(TextView) convertView.findViewById(R.id.lineOne);
                holder.lineTwo =
(TextView) convertView.findViewById(R.id.lineTwo);
                convertView.setTag
(holder);
           
} else {
               
holder = (ViewHolder) convertView.getTag();
           
}

            ListItem item = items.get(position);
            holder.lineOne.setText
(item.lineOne);
            holder.lineTwo.setText
(item.lineTwo);
           
return convertView;
       
}
    }

    static class ViewHolder {
       
TextView lineOne;
        TextView lineTwo;
   
}
}

Here’s how the XML layout file is for the list item (list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
 
  <TextView
    android:id="@+id/lineOne"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingTop="12dp"
    android:paddingLeft="12dp"
    android:textSize="18sp"
    android:textStyle="bold"
  />
 
  <TextView
    android:id="@+id/lineTwo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="12dp"
    android:paddingBottom="12dp"
  />
 
</LinearLayout>
 

Here’s how the applications looks like on an Android 2.3 emulator

You can grab the source for Android application above here.

So this basically all I have for now. I plan to go into detail by breaking down each part of the code samples I provided for all 3 platforms, or perhaps add another platform as well. I hope you found this useful.

How to enable Internet Tethering on a Samsung Omnia 7

I recently received a Samsung Omnia 7 and I think it’s a pretty awesome phone. But, Windows Phone 7 in general lags behind with a few things, one of these things is a built in internet tethering feature (like in the iPhone for example). Since I’m going away for a few days I don’t intend on going around with a 3G modem (my laptop doesn’t have a built in 3G modem), neither am I to keen on switching back to my iPhone. So I searched for a solution and stumbled upon a hack to enable launch the Omnia 7 Diagnostic Menu and the Micro USB Test.
Here’s what you need to do
  • Open the phone application
  • Dial  # # 634 # and press Call
  • This will launch the diagnostic menu
  • Enter  * # 7284 #
  • If the code above is entered properly then the Micro USB Test app launches 
  • Select Modem, Tethered Call
  • You are prompted to restart the device
  • Connect your Omnia 7 to your computer via USB

In my attempt I was prompted to install the Samsung USB Driver and Windows 7 provided me with a link. Try it out 🙂

Chris’ Puzzle Game on the Windows Phone 7 Marketplace

I got my first application published on the Marketplace. The process was surprisingly fast, took overnight to get it certified and another day before it appeared on the Marketplace. I have a video demo of the game here and I demonstrate how parts of the game was built in an article called Writing a Puzzle Game for Windows Phone 7 using XNA. Try the game out, I’d love to get some feedback. It’s a game made over a weekend and the main purpose was to experience the publishing process. If you have some comments, suggestions, or questions on the game then please send them to me and I’ll see what I can do.

How to launch the Marketplace in the Windows Phone 7 Emulator

You probably noticed by now that the default Windows Phone 7 emulator only contains Internet Explorer and the Settings. I stumbled upon a tip from Daniel Vaughan about Launchers and Choosers today and I learned about a task that can start up the Marketplace Hub. Unfortunately you will have to create an application that calls into the Launcher API to accomplish this.

Here’s what you need to do:

1) Create a new Silverlight Windows Phone Application
2) In your MainPage.cs and add a using directive to the Microsoft.Phone.Tasks namespace.
3) Add the following in the constructor of MainPage.cs after calling the InitializeComponent() method:

var task = new MarketplaceHubTask();
task.ContentType = MarketplaceContentType.Applications;
task.Show();

4) Launch the application and you should be good to go.

Here’s how the Marketplace looks like on the emulator:

Click here to see a list of supported launchers and choosers for Windows Phone 7. You can read more about Launchers and Choosers here.

How to use the keyboard in the Windows Phone 7 Emulator

The one thing that irritated me the most about the Windows Phone 7 emulator the first time I used it was that the host computer keyboard is not directly mapped to the emulator. This means you by default have to use the software input panel that is built in Windows Phone 7.

I immediately looked for a solution and found some MSDN documentation on the keyboard mappings for the emulator.

To enable the keyboard in the emulator – press the PAGE UP key or PAUSE/BREAK key.

To disable the keyboard in the emulator – press the PAGE DOWN key PAUSE/BREAK key.

If you want to learn more then I suggest you check out this article called Keyboard Mapping for Windows Phone Emulator