(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

WP7 for iPhone and Android Developers - Hardware and Device Services

(4 votes)
Kevin Hoffman
>
Kevin Hoffman
Joined Feb 01, 2011
Articles:   10
Comments:   1
More Articles
0 comments   /   posted on Mar 15, 2011
Categories:   Windows Phone , General

This article is part 4 in a 12-part article series on Windows Phone 7 for iPhone and Android Developers.

iOS and Android Device Capabilities

In just a few short years, we as consumers have gone from being surprised when our phones were able to check e-mail wirelessly to demanding an incredible amount of features and capabilities from our smart phones. We want our phones to be able to browse the web, access our mailboxes, participate in our social networks, store our contacts, take pictures, send pictures, figure out where we are, and even figure out the magnitude and direction of the forces currently accelerating our phone. Let’s face it – we expect an awful lot from our phones.

Much of this demand is due to revolutionary phones like the original iPhone that changed the way most consumers view their phones. Phones are no longer just devices for making phone calls, they are mobile extensions of our digital lives and they serve as gateways to our digital footprints – giving us access to our files, friends, and important information.

As the capabilities of each Android device are specific to that device, manufacturer, and cellular provider I will probably do most of my comparison in this article to the features available on iOS devices like the iPhone and iPad. Suffice it to say, however, that if you can’t find all of these features on a single Android phone, you can probably find some combination of them on different phones.

In this next section I’m going to talk about three different ways in which you can harness the power of your Windows Phone 7 device: Launchers (tasks that launch system-level facilities), Choosers (tasks that retrieve system-level data), and Hardware Services and sensors (such as GPS and accelerometer services).

Using Launchers

Whether you’re getting your current position from the GPS, using the accelerometer as a video game controller, or just trying to figure out who you should e-mail your latest cute kitten picture to – the device you’re using needs to draw a line between giving the developers and users what they want while still ensuring system safety and high performance.

One of the ways Windows Phone 7 give developers access to certain system functionality without compromising security and performance is through the use of Launchers. Launchers allow your application to launch components of Windows Phone 7.

One of the launchers available to you is the SavePhoneNumberTask. Like all launchers, you simply instantiate it, provide some configuration information, set up a handler for when the launcher has completed, and then call Show():

 1: SavePhoneNumberTask phoneSave = new SavePhoneNumberTask();
 2: phoneSave.PhoneNumber = "8675309";
 3: phoneSave.Completed += (s, e) => 
 4:     { MessageBox.Show("Phone number task complete."); };
 5: phoneSave.Show();

This launcher will bring up a Windows Phone 7 dialog that saves the phone number supplied to a new or existing profile. Windows Phone 7 allows single profiles to be linked to multiple information sources (such as Facebook, Google, Hotmail, etc). In addition to saving phone numbers to profiles, you can also save e-mail addresses with the SaveEmailAddressTask.

You can perform a search that will display the same results as if the user had pressed the search hardware button using the SearchTask:

 1: SearchTask search = new SearchTask();
 2: search.SearchQuery = "kevin hoffman";
 3: search.Show();

The following screenshot shows what appears after executing the search task:

You can launch a web browser using the WebBrowserTask or launch a media player that is pre-configured to point to a specific piece of local or remote media using the MediaPlayerLauncher class:

 1: MediaPlayerLauncher mediaLauncher = new MediaPlayerLauncher();
 2: mediaLauncher.Controls = MediaPlaybackControls.FastForward | 
 3:                          MediaPlaybackControls.Pause | 
 4:                          MediaPlaybackControls.Stop;
 5: mediaLauncher.Location = MediaLocationType.Install;
 6: mediaLauncher.Media = new Uri("Media/Bear.wmv", UriKind.Relative);
 7: mediaLauncher.Show();

Your application can initiate a phone call using the PhoneCallTask or send a text message using the SmsComposeTask and you can even begin composing an e-mail on behalf of your application users with the EmailComposeTask.

To recap, here’s a list of the launchers that allow your application to initiate system-level activities:

  • SavePhoneNumberTask
  • SaveEmailAddressTask
  • SearchTask
  • WebBrowserTask
  • MediaPlayerLauncher
  • PhoneCallTask
  • SmsComposeTask
  • EmailComposeTask

iOS and Android both allow varying levels of access to these types of capabilities. One thing to keep in mind is that often with iOS when a particular function belongs to an App rather than the OS, it can be difficult to directly manipulate the use of that system resource. Windows Phone 7’s launchers and tasks give us very good control over these facilities. Also note that there is no launcher task that specifically creates a new profile, only tasks that allow you to associate phone numbers and e-mail addresses with existing profiles or new profiles. These new profiles are only created at the user’s request, not your application’s. This is a recurring theme – any time WP7 is about to do something that affects potentially important data, it will get interactive, live confirmation from a user before proceeding.

At the moment there is no launcher in WP7 to add a calendar event.

Using Choosers

Where launchers allow your applications to initiate system-level functionality like launching a web browser or storing e-mail addresses and phone numbers, Choosers allow for your applications to perform user-assisted queries of system data. In other words, the same security that WP7 requires before making changes to important data is also used to require the intervention of a live user before being able to query system data.

Here is a list of some of the choosers (often called pickers, especially by those with iOS backgrounds) available in WP7:

  • PhoneNumberChooserTask – This task pulls up a dialog that lets the user search through the list of people in the people hub and choose a single phone number from among them.
  • EmailAddressChooserTask – This task pulls up the same dialog as PhoneNumberChooserTask but it chooses an e-mail address instead. Note that people who do not have e-mail addresses associated with them will not even show up in the list of available choices.
  • PhotoChooserTask – This task lets you pick from among stored photos or take a new picture, returning a reference to the picture when the task is complete.

Here is a sample that illustrates how to use a PhotoChooserTask to set the contents of an Image object (seen in XAML as an <Image…/> element) on an application page to whatever photo was selected:

 1: PhotoChooserTask photoChooser = new PhotoChooserTask();
 2: photoChooser.ShowCamera = true;
 3: photoChooser.Completed += (s, e) =>
 4:     {
 5:         if (e.TaskResult == TaskResult.OK)
 6:         {
 7:             BitmapImage bmp = new BitmapImage();
 8:             bmp.SetSource(e.ChosenPhoto);
 9:             targetImage.Source = bmp;
 10:         }
 11:     };
 12: photoChooser.Show();

iOS lets you bring up pickers that give users access to similar system-level resources, including the ability to capture new photos and store them in your application. As you’ll see throughout this article, pretty much everything you can do with your Android or iOS smart phone, you can do with your Windows Phone 7 (and some things your WP7 can do that others can’t!)

Using Hardware Services and Sensors

There are a wide variety of things you can make your WP7 device do as well as a lot of information you can obtain from its built-in sensors. One of my personal favorites is the ability to directly control its ability to vibrate. This comes in handy if you’re making a game and you want the phone to vibrate when the player gets hit or chooses a wrong answer:

 1: VibrateController.Default.Start(TimeSpan.FromSeconds(1));
 2: VibrateController.Default.Stop();

 

If you want to use the vibration controller, you’ll need to add a reference to the Microsoft.Devices Assembly.

Another piece of hardware that you can control from the WP7 SDK is the radio tuner. That’s right, every Windows Phone 7 device must have an FM radio tuner. For the devices I have seen so far, the antenna for this tuner is in the headphones that come with the device. If the antenna-headphones are not attached when you attempt to turn on the FM radio, you will get an exception:

 1: try
 2: {
 3:     FMRadio radio = Microsoft.Devices.Radio.FMRadio.Instance;
 4:     radio.Frequency = 96.5;
 5:     radio.PowerMode = RadioPowerMode.On;
 6:     Debug.WriteLine("Radio signal strength : {0}", radio.SignalStrength);
 7: }
 8: catch (RadioDisabledException rde)
 9: {
 10:     MessageBox.Show("the radio is not available on this device.");
 11: }

If you are a fan of easter eggs, then try setting the radio to different frequencies from inside the WP7 simulator. You might find some interesting radio stations (or at least interesting music loops).

 

Accelerometers have become incredibly popular since their appearance in the original iPhone (as well as other devices though the iPhone is certainly among the most well-known accelerometer-bearing smartphones). Accelerometers measure the acceleration of a device along 3 axes: X, Y, and Z. These correspond to the “Normal” or the direction pointing downward toward the earth due to the acceleration caused by gravity. Accelerations are measured as deviations from the constant pull of gravity. What does this all mean? Well, first of all it means that if you tried to steer your racing car game on the moon using your iPhone, you’d probably end up crashing. Secondly, it means that usually we have to do a little bit of math to convert these raw numbers into something usable like rotation angles used to play games or rotate UI elements.

The following is a snippet of code from an application that has a button to toggle on or off the accelerometer sampling. When the accelerometer is active, we have an event handler that responds to new values and updates some UI elements accordingly (I won’t get into the math required to translate accelerometer values into things like controller rotation – there are plenty of physics and math websites available that can help you with that):

 1: private void startAccelButton_Click(object sender, RoutedEventArgs e)
 2: {
 3:     if (accel == null)
 4:     {
 5:         accel = new Accelerometer();
 6:         accel.ReadingChanged += 
 7:           new EventHandler<AccelerometerReadingEventArgs>(
 8:           accel_ReadingChanged);
 9:         try
 10:         {
 11:             accelerometerStatusText.Text = "Accelerometer starting.";
 12:             accel.Start();
 13:         }
 14:         catch (AccelerometerFailedException ex)
 15:         {
 16:             accelerometerStatusText.Text = "Accelerometer error.";
 17:         }
 18:     }
 19:     else
 20:     {
 21:         try
 22:         {
 23:             accel.Stop();
 24:             accel = null;
 25:             accelerometerStatusText.Text = "Accelerometer Stopped.";
 26:         }
 27:         catch (AccelerometerFailedException ex)
 28:         {
 29:             accelerometerStatusText.Text = 
 30:               "Error stopping Accelerometer.";
 31:         }
 32:     }
 33: }
 34:  
 35: void accel_ReadingChanged(object sender, 
 36:   AccelerometerReadingEventArgs e)
 37: {
 38:     Deployment.Current.Dispatcher.BeginInvoke(
 39:       () => HandleNewReading(e));
 40: }
 41:  
 42: void HandleNewReading(AccelerometerReadingEventArgs e)
 43: {
 44:     xText.Text = e.X.ToString();
 45:     yText.Text = e.Y.ToString();
 46:     zText.Text = e.Z.ToString();
 47: }
 48: }

Don’t worry if some of this code looks a little weird, but you should be able to get the general idea of what’s going on. The call to Deployment.Current.Dispatcher.BeginInvoke is required because we receive samples from the accelerometer on a background thread and we’re not allowed to update UI elements on background threads – only on the dispatcher (foreground or main) thread.

This concept of forwarding UI-changing method calls onto a foreground thread should be familiar to iOS developers who regularly have to write Objective-C code that looks like this (functionally equivalent to using the dispatcher’s BeginInvoke method in WP7):

 1: [self performSelectorOnMainThread:@selector(handleNewReading) 
 2:     withObject:e 
 3:     waitUntilDone:false];

No discussion of interaction with smart phone hardware would be complete without talking about the GPS. With today’s smart phones (and incredibly demanding consumers), we’re getting to the point where we almost take GPS capabilities for granted. If you’re in the market for a smart phone, you’re probably going to laugh at any phone that doesn’t have some form of GPS capability.

To interact with WP7’s built-in GPS device, you simply need to request location information using a pattern that should look familiar to iOS developers who have used the GPS before. Here’s some code that toggles GPS monitoring using an object of type GeoCoordinateWatcher called watcher:

 1: private void startLocationButton_Click(object sender, 
 2:         RoutedEventArgs e)
 3:      {
 4:          if (watcher == null)
 5:          {
 6:              watcher = 
 7:                new GeoCoordinateWatcher(GeoPositionAccuracy.High);
 8:              watcher.MovementThreshold = 20; // compensate for noise
 9:              watcher.StatusChanged += 
 10:                new EventHandler<GeoPositionStatusChangedEventArgs>(
 11:                                  watcher_StatusChanged);
 12:              watcher.PositionChanged += 
 13:                new EventHandler<
 14:                 GeoPositionChangedEventArgs<GeoCoordinate>>(
 15:                                  watcher_PositionChanged);
 16:              watcher.Start();
 17:          }
 18:      }
 19:  
 20:      void watcher_PositionChanged(object sender, 
 21:        GeoPositionChangedEventArgs<GeoCoordinate> e)
 22:      {
 23:          latitudeText.Text = 
 24:            e.Position.Location.Latitude.ToString("0.000");
 25:          longitudeText.Text = 
 26:            e.Position.Location.Longitude.ToString("0.000");
 27:          altitudeText.Text = 
 28:            e.Position.Location.Altitude.ToString("00000.00");
 29:      }
 30:  
 31:      void watcher_StatusChanged(object sender, 
 32:         GeoPositionStatusChangedEventArgs e)
 33:      {
 34:          switch (e.Status)
 35:          {
 36:              case GeoPositionStatus.Disabled:
 37:                  if (watcher.Permission == 
 38:                      GeoPositionPermission.Denied)
 39:                  {
 40:                      watcherStatus.Text = 
 41:                 "Application is not allowed to use location services.";
 42:                  }
 43:                  else
 44:                  {
 45:                      watcherStatus.Text = 
 46:                       "Location services not working properly.";
 47:                  }
 48:                  break;
 49:              case GeoPositionStatus.Initializing:
 50:                  startLocationButton.IsEnabled = false;
 51:                  watcherStatus.Text = "Initializing...";
 52:                  break;
 53:              case GeoPositionStatus.NoData:
 54:                  stopLocationButton.IsEnabled = true;
 55:                  watcherStatus.Text = "Active, but no location data.";
 56:                  break;
 57:              case GeoPositionStatus.Ready:
 58:                  watcherStatus.Text = "Location data is available.";
 59:                  stopLocationButton.IsEnabled = true;
 60:                  break;
 61:          }
 62:      }
 63:  
 64:      private void stopLocationButton_Click(object sender, 
 65:         RoutedEventArgs e)
 66:      {
 67:          watcher.Stop();
 68:          watcherStatus.Text = "(not monitoring GPS)";
 69:      }

If you run code like this in the WP7 simulator, you will notice that you never receive GPS coordinates and the status of the watcher immediately changes to “Active, but no data.”. If you’re interested in GPS, there are plenty of articles online illustrating how to simulate GPS data using things like the Reactive Extensions (I’ll talk about those in another article, so stay tuned!).

Summary

What this entire article really boils down to is this: Your application can either be limited by the phone platform on which it runs or it can be enhanced by it. When you’re deciding on a platform for your application, take a long hard look at what system services are available for your application to launch and query, what hardware can you manipulate and what sensors can you read? Windows Phone 7 provides an incredible amount of control of services and hardware, allowing your applications to initiate e-mails, text messages, save phone numbers and e-mail addresses, initiate geo-aware searches, query phone numbers and e-mail addresses, access the accelerometer and even query GPS, control and FM radio, and make the phone vibrate.

Given what I’ve already covered of the simplicity and power of C#, XAML, Silverlight, and the Windows Phone 7 SDK, adding all of these system and hardware level capabilities makes WP7 an even more compelling choice as a potential platform on which to build your application.

About the Author

Kevin Hoffman (http://www.kotancode.com/) is a Systems Architect for Oakleaf Waste Management (http://www.oakleafwaste.com/), freelance developer, and author of multiple books including the upcoming WP7 for iPhone Developers and co-author of books such as ASP.NET 4 Unleashed and SharePoint 2007 Development Unleashed. He is the author of the Kotan Code blog and has presented at Apple's WWDC twice and guest lectured at Columbia University on iPhone development.

 


Subscribe

Comments

No comments

Add Comment

Login to comment:
  *      *       

From this series