Detecting Emulator on Windows Phone 7#

In some instances when developing your Windows Phone 7 app using Silverlight you may want to know if your code is running within the emulator or within a real device.  For example in my previous post on shake detection on Windows Phone 7 I didn’t want to create an new AccelerometerWithShakeDetection object if it was running in the emulator since the hardware is not available in the emulator.

In .NET Compact Framework it was a little bit of a pain to get this information as you have to PInvoke and have to know the native calls to get this information as follows

[DllImport("coredll.dll")]
private static extern int SystemParametersInfo(uint uiAction, 
uint uiParam, string pvParam, uint fWiniIni); private const uint SPI_GETOEMINFO = 258; public static bool IsEumlator() { string szOEMInfo = " "; string strOEMInfo = ""; // Get OEM Info int ret = SystemParametersInfo(SPI_GETOEMINFO, szOEMInfo.Length, szOEMInfo, 0); if (ret != 0) { strOEMInfo = szOEMInfo.Substring(0, szOEMInfo.IndexOf('\0')); return strOEMInfo.Equals("Microsoft DeviceEmulator"); } else throw new Exception("Unable to determine"); }

Using Silverlight for Windows Phone 7, you can now use the System.Environment.DeviceType which simply returns Unknown, Emulator or Device.

    if (System.Environment.DeviceType == DeviceType.Emulator)
    {
        MessageBox.Show("You are running on the emulator.");
    }
    else if (System.Environment.DeviceType == DeviceType.Unknown)
    {
        MessageBox.Show("You are running on an unknown device.");
    }
    else
    {
        MessageBox.Show("You are running on a device");
    }

Again, no more PInvokes since it’s not supported and the code is a lot easier to write and maintain.

So far in my working with Windows Phone 7 and Silverlight I haven’t required PInvoke functionality so far.  We’ll see what happens in the future as the SDK gets out of CTP and we get customer projects but so far so good!


Saturday, May 29, 2010 1:42:12 AM (Eastern Daylight Time, UTC-04:00) #    Comments [1]  |  Trackback

 

Shake Detection on Windows Phone 7#

Back in Sept 2009 I did a few presentations for FITC Mobile 2009 and in the sample code I included a modified version of the Sensor API available on Codeplex.  The modified version of the API included some code that leveraged the accelerometer on some devices to detect when a device was shaken.  This code base was for Windows Phone 6.x and used .NET Compact Framework 3.5.  Essentially all you would have to do is wire up a ShakeDetected event and whenever the API detects a shake you would be notified via an event.

private IGSensor m_sensor;

public Form1()
{
    InitializeComponent();

    m_sensor = GSensorFactory.CreateGSensor();
    m_sensor.ShakeDetected += m_sensor_ShakeDetected;
  
}

void m_sensor_ShakeDetected(object sender, EventArgs e)
{
    //Invoke into the main thread since we are coming form a background thream
    this.Invoke(new EventHandler(delegate(object s, EventArgs ea)
    {
        //Code once shake is detected
        MessageBox.Show("Shake Detected");
    }));

}

Couple of things I didn’t like about this code.

  1. There is a thread running in the background doing a calculation of the X,Y,Z values and determining whether a shake has occurred.  This will drain the battery.
  2. It’s not a standard API and does not work on all devices because either the device does not have the hardware or the PInvokes are specific for only one OEM such as HTC.

To try it out for your self download the sample code for shake detection here. (Find it under Release Presentation Code\New Windows Mobile 6.5\Demo1\ShakeDetection).

Shake Detection On Windows Phone 7

Since the development environment for Windows Phone 7 is completely different now and uses Silverlight, the ‘shake detection’ code essentially is useless but that doesn’t mean the code can’t be ported over.

The good thing is Windows Phone 7 introduces standard hardware and standard APIs for sensors which should alleviate some developer pains from previous Windows Phone versions.  All Windows Phone 7 devices from OEMs will include an accelerometer so no more worrying about code not working.  Before I get into how to detect shake, see here for an overview of the accelerometer on Windows Phone 7.

To get shake detection working on Windows Phone 7, I had to wrap the AccelerometerSensor class within a wrapper class called AccelerometerSensorWithShakeDetection.  Using the new class is pretty straight forward and basically have to create an instance of the class and wire up the ShakeDetected event handler.

AccelerometerSensorWithShakeDetection m_shakeSensor;

public MainPage()
{
    InitializeComponent();

    m_shakeSensor = new AccelerometerSensorWithShakeDetection();
}

private void btnStart_Click(object sender, RoutedEventArgs e)
{
    m_shakeSensor.ShakeDetected += m_shakeSensor_ShakeDetected;
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    m_shakeSensor.ShakeDetected -= m_shakeSensor_ShakeDetected;
}

void m_shakeSensor_ShakeDetected(object sender, EventArgs e)
{
    lblShakeStatus.Text = string.Format("Shake Detected @ {0}",
                  DateTime.Now.ToString("hh:mm:ss")); }

AccelerometerSensorWithShakeDetection implementation is different from the previous version because we now have a standard API.  Internally we wire up the AccelerometerSensor.ReadingChanged event when a user wires up the ShakeDetected event and call the AccelerometerSensor.Start and AccelerometerSensor.Stop when the AccelerometerSensorWithShakeDetection.Start/Stop methods are called.

public event EventHandler ShakeDetected
{
    add
    {
        m_ShakeDetectedHandler += value;
        m_sensor.ReadingChanged += Default_ReadingChanged;
    }
    remove
    {
        m_ShakeDetectedHandler -= value;
        m_sensor.ReadingChanged -= Default_ReadingChanged;
    }
}
        
public void Start()
{

    if (m_sensor != null)
        m_sensor.Start();
}

public void Stop()
{
    if (m_sensor != null)
        m_sensor.Stop();
}

When the reading change event occurs, we run our shake detection logic to see if the user has shaken the device.

private void Default_ReadingChanged(object sender, AccelerometerReadingAsyncEventArgs e)
{
    //Code for checking shake detection
    if (e.Value.State == SensorState.Ready)
    {
        AccelerometerReading reading = e.Value.Value;
        DateTimeOffset timeStamp = e.Value.Timestamp;
        try
        {
            if (!shaking && this.CheckForShake(m_lastReading, reading, 
                       shakeThreshold) && shakeCount >= 5) { //We are shaking shaking = true; shakeCount = 0; OnShakeDetected(); } else if (this.CheckForShake(m_lastReading, reading, shakeThreshold)) { shakeCount++; } else if (!this.CheckForShake(m_lastReading, reading, 0.2)) { shakeCount = 0; shaking = false; } m_lastReading = reading; } catch { /* ignore errors */ } } } private void OnShakeDetected() { if (this.m_ShakeDetectedHandler != null) this.m_ShakeDetectedHandler(this, EventArgs.Empty); } private bool CheckForShake(AccelerometerReading last,
                            AccelerometerReading current, double threshold) { double deltaX = Math.Abs((double)(last.X - current.X)); double deltaY = Math.Abs((double)(last.Y - current.Y)); double deltaZ = Math.Abs((double)(last.Z - current.Z)); return (deltaX > threshold && deltaY > threshold) || (deltaX > threshold && deltaZ > threshold) || (deltaY > threshold && deltaZ > threshold); }

When a shake is detected, the ShakeDetected handler is called to notify the listeners.

So porting code from previous Windows Phone versions to Windows Phone 7 is definitely possible because we are still using Managed code.  Some advantages to the new code are

  1. Standard APIs are used for the Accelerometer
  2. No threads running in the background to detect shake.  Instead an event based mechanism is used which will preserve the user experience and preserve the battery life.

One thing to note, to code compiles and runs on the emulator, but because I don’t have a real Windows Phone 7 device, I cannot test the code.  The version for .NET CF 3.5 works and the shake detection logic is essentially the same for Windows Phone 7 so I’m assuming it will work.  But if anyone in the product group wants to test on a real device (or send me a real device :) please do and let me know if it works.

Once I get a real device, I’ll test and update this post.  In the meantime, download the shake detection source code here to take a peak.


Saturday, May 29, 2010 1:04:58 AM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  |  Trackback

 

OAuth with Silverlight for Windows Phone 7#

In my last post I wrote about the Silverlight WebBrowser control on Windows Phone 7 and how to communicate with a web page hosted inside the control and your Windows Phone 7 app.  The example in that post was pretty trivial, so why not try something like OAuth and Twitter.

For more background on how OAuth and Twitter work check the Authentication Overview on dev.twitter.com.

In short here is the process (overly simplified) to authenticate a twitter user

  1. Register your app with Twitter and get a key
  2. Within app, get an request token
  3. With the WebBrowser control, navigate to Authentication URL
  4. Wait till the user authenticates.
  5. Get an access token
  6. Make secure calls

After becoming familiar with OAuth, first thing I decided to do was find an OAuth library for Silverlight.  The one I found most useful and easily portable to Windows Phone 7 was sample code in the book Professional Twitter Development by Daniel Crenna.  Unfortunately, this did  not compile without a few changes on WP7.  Here is a quick summary of the changes I made

  1. Change all HttpWebRequests to be async since sync requests are not supported
  2. Added callback param to all methods to get responses back to the UI
  3. Created and OAuthEventArgs class
  4. Modified support to POST web requests
  5. Added helper methods to ParseQueryString and HexEscape characters
  6. Added a TwitterOAuth class to contain all tokens, Urls and various other items.

Next thing I had to do was wire up the code to enable the user to authenticate via OAuth with Twitter.  Basically all you have to do is get a “request token” then navigate to the “authentication Url” for the user to enter their credentials.  Here is the code

OAuth.GetRequestToken(m_twitterOAuth.RequestTokenUrl,
    m_twitterOAuth.ConsumerKey,
    m_twitterOAuth.ConsumerSecret,
    new EventHandler<OAuthEventArgs>((o, args) =>
    {

        if (args.IsError)
            this.Dispatcher.BeginInvoke(() => MessageBox.Show(args.ErrorMessage));
        else
        {
            //extract the items
            Dictionary<string, string> results = 
                              Helpers.ParseQueryString(args.Response); foreach (var item in results) { if (item.Key.Equals("oauth_token")) m_twitterOAuth.Token = item.Value; else if (item.Key.Equals("oauth_token_secret")) m_twitterOAuth.TokenSecret = item.Value; } //Wait till the browser loads while (!m_browserLoaded) Thread.Sleep(100); //once loaded invoke the browser to go to twitter auth page this.Dispatcher.BeginInvoke(() => { webBrowser1.Navigate(new Uri(m_twitterOAuth.AuthenticationUrl)); }); } }));

When asking for a request token, you can specify a callback url that twitter will navigate to when the user successfully authenticates.  Next step is to create an HTML page that will invoke a method within our WP7 application.  The HTML Page is as follows and is very straight forward.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>TwitterCallback</title>
     <script type="text/javascript">
         function InvokeApp(input) {
             window.external.Notify(window.location.href);
         }

    </script>
</head>
<body onload="InvokeApp()">
</body>
</html>

The method inside our WP7 app will parse the url which contains details on the authentication then goes out and gets the access token to make secure calls

void webBrowser1_ScriptNotify(object sender, NotifyEventArgs e)
{
    //we are back from authentication so extract the verifier
    try
    {
        Uri uri = new Uri(e.Value);
        //parse the query string
        Dictionary<string, string> results = Helpers.ParseQueryString(uri.Query);    

        foreach(var item in results)
        {
            if (item.Key.Equals("oauth_verifier"))
                m_twitterOAuth.Verifier = item.Value;
        }

        //hide the web browser control
        this.Dispatcher.BeginInvoke(() =>
        {
            textBlock1.Text = "Contacting twitter to get access to your twitter 
account. Please be patient :)"
; textBlock1.Visibility = System.Windows.Visibility.Visible; webBrowser1.Visibility = System.Windows.Visibility.Collapsed; }); //now that we have the verifier get the access token OAuth.GetAccessToken(m_twitterOAuth.AccessTokenUrl, m_twitterOAuth.ConsumerKey, m_twitterOAuth.ConsumerSecret, m_twitterOAuth.Token, m_twitterOAuth.TokenSecret, new EventHandler<OAuthEventArgs>((obj, args) => { //handler when the get access token call returns if (args.IsError) this.Dispatcher.BeginInvoke(() =>
                               MessageBox.Show(args.ErrorMessage)); else { //extract the items results = Helpers.ParseQueryString(args.Response); foreach (var item in results) { if (item.Key.Equals("oauth_token")) m_twitterOAuth.Token = item.Value; else if (item.Key.Equals("oauth_token_secret")) m_twitterOAuth.TokenSecret = item.Value; else if (item.Key.Equals("user_id")) m_twitterOAuth.UserId = item.Value; else if (item.Key.Equals("screen_name")) m_twitterOAuth.ScreenName = item.Value; } //update the label this.Dispatcher.BeginInvoke(() => { MessageBox.Show(textBlock1.Text,
                                   "Authorized for Twitter", MessageBoxButton.OK); btnSignOut.Visibility = btnPostTweet.Visibility =
                                     txtTweet.Visibility = Visibility.Visible; textBlock1.Visibility = Visibility.Collapsed; }); //save the settings SaveTwitterOAuth(); } })); } catch (Exception ex) { this.Dispatcher.BeginInvoke(() => MessageBox.Show(ex.Message)); } }

Now that we are authenticated we can make a ‘Tweet’ from with our application as follows

private void btnPostTweet_Click(object sender, RoutedEventArgs e)
{
    if (txtTweet.Text.Length > 140)
    {
        MessageBox.Show("Message is greater than 140.  Cannot post");
    }
    else
    {
        OAuth.GetProtectedResource(
            string.Format(m_twitterOAuth.StatusUpdateUrl, 
                  HttpUtility.UrlEncode(txtTweet.Text)), "POST", m_twitterOAuth.ConsumerKey, m_twitterOAuth.ConsumerSecret, m_twitterOAuth.Token, m_twitterOAuth.TokenSecret, new EventHandler<OAuthEventArgs>((obj, args) => { //the post is back so parse the response //handler when the get access token call returns if (args.IsError) this.Dispatcher.BeginInvoke(() =>
                             MessageBox.Show(args.ErrorMessage)); else { this.Dispatcher.BeginInvoke(() => { MessageBox.Show(args.Response,"Tweet Posted",
                                           MessageBoxButton.OK); txtTweet.Text = string.Empty; }); UpdateUsernameLabel(); } })); } }

Here is a screen shot of a test tweet

image One of the advantages of using OAuth with Twitter is you get your ‘application name’ in the ‘via’ section instead of it saying ‘posted from web’.  Also, since Basic Authentication is no longer supported by Twitter, your only option is either OAuth or XAuth.  Considering with XAuth you have to email twitter and convince them to give you access to that, OAuth is the easier way to go.

Here are some screen shots of the Windows Phone 7 client.

wp7oauthtwitter

 

You can download the source code here.  I have no plans on building a Twitter client for Windows Phone 7 as I have a feeling someone out there is probably building one :)

Any feedback let me know via here or via Twitter.

NOTES: The app will not compile until you remove the #error to add your registered app key.  Also, make sure you change the timezone and set the correct time on the emulator or else the OAuth signature generation will not work.


Friday, May 28, 2010 11:59:08 PM (Eastern Daylight Time, UTC-04:00) #    Comments [1]  |  Trackback

 

Windows Phone 7 Webcast with Microsoft Canada#

Yesterday I had a chance to do a webcast with Microsoft Canada on the developer experience for Windows Phone 7 and getting developers ramped up.  If you missed it you can get it on demand here : In the Know With Windows Phone 7 

There were a few demos that I went through during the webcast which are

  1. FirstApp – typical hello world type app
  2. AppNavigation – navigating and using the back button
  3. InputScope – setting different input scope/SIP types
  4. Launchers and Choosers – examples of using it
  5. Multimedia – playing a wmv file
  6. Notifications – sending toast and tile notifications

These are very introductory demos and no error checking has been built in so make sure you add that.  You can download the source here

If you have any feedback or comments on the webcast feel free to contact me at mark [at] redbitdev [dot] com.


Friday, May 28, 2010 2:38:22 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  |  Trackback

 

Silverlight WebBrowser Control and Windows Phone 7#

Silverlight for Windows Phone 7 contains a WebBrowser control and there is nothing to impressive about that other than you have the ability to load a web page within your Silverlight application. But there is a hidden gem, the ability for two way communication with the webpage within your Silverlight app. There is a mini browser sample available on the Windows Phone Development section on MSDN which basically places a web browser control with a textBox and button so you can navigate to a URL. If you know the basics of using the control skip to the Hidden Gem section below.

The Basics

Using the WebBrowser control is nothing too exciting or complicated.  Just drag it from your ToolBox within Visual Studio Express for Windows Phone and drop it on your page in the designer.  Visual Studio will automatically add a reference to Microsoft.Phone.Controls.Webbrowser and Microsoft.Phone.Controls.WebbrowserInterop.

image

Then doing a quick call to WebBrowser.Navigate() on the button click event and your done.  Again nothing too exciting or complicated but can be useful in some situations within your app.

The Hidden Gem

The hidden gem I learned during Mike Harsh’s MIX10 session.  I was really excited about it because it solved a few problems I had on previous versions. This gem comes in the form of the WebBrowser.IsScriptEnabled property.    Basically this property will allow the loaded page within the webBrowser control invoke the ScriptNotify Event handler within your Silverlight app.  But that’s not all, using the WebBrowser.InvokeScript allows the Silverlight for Windows Phone app invoke a Javascript function on the web page loaded within the webBrowser control.  Basically you have two way communication which could be valuable in some situations.  Here’s how it works.

First step is making sure the IsScriptEnabled property is set to true.  This allows the communication to work between the two layers.  Default value is false.

image

In the sample code, I created a textBox to type in the URL to browse to and a button to call WebBrowser.Navigate().  I also created an extra textBox and button to invoke a javascript function within the loaded web page.  You will also have to wire up the WebBrowser.ScriptNotify event.  I did this via Xaml but can also be done in code as follows:

webBrowser1.ScriptNotify+=new EventHandler<NotifyEventArgs>(webBrowser1_ScriptNotify);

and the handler is just a messagebox to show the data received

private void webBrowser1_ScriptNotify(object sender, NotifyEventArgs e)
{
    MessageBox.Show(
string.Format("New value received from web browser control (\"{0}\")", e.Value)); }

To invoke a script in the web browser control use the InvokeScript method passing in the Javascript method  to invoke and the string to send as follows:

webBrowser1.InvokeScript("DataReceivedFromPhoneApp", textBox1.Text);

The page is very basic and looks like this.

image

The other side of this sample is a web page to load.  Again I kept it basic but here is the web page rendered

image and the source

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <
html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta name="mobileoptimized" content="480" /> <title>SamplePage1</title> <script type="text/javascript"> function DataReceivedFromPhoneApp(input) { textReceived.innerHTML = input; return true; } function SendDataToPhoneApp() { window.external.Notify(textToSend.value); } </script> </head> <body> <div> Enter your text: <input name="textToSend" type="text" value="send to app" /> </div> <div> <input type="button" value="Send to Phone" onClick="SendDataToPhoneApp()"/> <br /> <br /> </div> <div>Value received from phone app:</div> <div id="textReceived" style="font-size: x-large; font-weight: bold; color:
#800000;
border: thin solid #000000"></div> </body> </html>

When you run the app an navigate to the page (I hosted it on my local IIS on my dev machine) it will render up the web page.  Clicking the button inside the web browser control produces the following.

image

And clicking the button within the Silverlight app modifies the html via javascript producing the following

image

Conclusion

There you have it two way communication between your Silverlight for Windows Phone 7 app and a web page within the WebBrowser control.

Pre-Windows Phone 7 using .NET Compact Framework this was possible but again with a lot of extra effort.  As far as I know, you would need to create an ActiveX control, register it on the device and somehow communicate with the web browser and the .NET CF app using some form of Inter-Process Communication (IPC).  Not fun or easy!

Explore some more and download the sample code here


Thursday, May 13, 2010 7:19:15 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  |  Trackback

 

All content © 2010, Mark Arteaga
Related Sites
Archives
Sitemap
Disclaimer

Powered by: newtelligence dasBlog 1.9.7174.0

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Send mail to the author(s) E-mail

Theme design by Jelle Druyts