Windows Phone 7 third-party applications run
in a sandbox that is isolated from other third-party applications, as
well as from the underlying operating system and hardware, except where
APIs are surfaced.
One of the primary namespaces where a developer can integrate with the hardware and software platform is the Microsoft.Phone.Tasks namespace. The namespaces consists of launchers and choosers. The following are the launchers:
EmailComposeTask
MarketplaceDetailTask
MarketplaceHubTask
MarketplaceReviewTask
MarketplaceSearchTask
MediaPlayerLauncher
PhoneCallTask
SearchTask
SMSComposeTask
WebBrowserTask
Here are the choosers:
CameraCaptureTask
EmailAddressChooserTask
PhoneNumberChooserTask
PhotoChooserTask
SaveEmailAddressTask
SavePhoneNumberTask
Many of the launchers and choosers must be tested on a
device, because the emulator does not include the full Windows Phone
user experience with e-mail accounts, marketplace, and the like.
1. Debugging Launchers and Choosers
When debugging many of the launchers and choosers,
the connection to Zune may prevent the application from running. To
debug your application, you must use the WPConnect tool that was made available in the Windows Phone Developer Tools October and January updates. Here is a link:
http://create.msdn.com/en-us/home/getting_started
Once installed, the WPConnect tool is located here on my machine:
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools\WPConnect
To use the tool, run Visual Studio 2010 and connect a
device to your PC via the Zune client. Once connected, close Zune and
run WPConnect via a command prompt. It will display a message that the
device is connected. If you disconnect the device from the cable, you
will have to repeat the process. Figure 1 shows a few runs just to show how easy it is to enable debugging when testing media such as the pictures hub or the MediaPlayerLauncher task.
2. Launchers
Launchers display UI to send the user to another part
of the phone's functionality. When the user clicks the Back hardware
button, he or she is returned to your application. Launchers are "fire
and forget" in that they do not return information back to the
application.
2.1. EmailComposeTask
The EmailComposeTask class allows the user to send e-mail from an application. You can configure the To, Cc, Subject, and Body of the e-mail message via properties. It is not possible to attach a file to the e-mail. Also, the Body property takes a string of text, so formatting such as HTML formatting the e-mail message is not supported. Listing 1 has the code for the EmailComposeTask sample.
Example 1. EmailComposeTask Code
private void textBlock1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//cause an exception and then send an error report.
try
{
int num1 = 3;
int num2 = 3;
int num3 = num1 / (num1 - num2);
}
catch (Exception err)
{
EmailComposeTask task = new EmailComposeTask();
task.To = "[email protected]";
task.Subject = "Customer Error Report";
//Size StringBuilder appropriately
StringBuilder builder;
if (null == err.InnerException)
builder = new StringBuilder(600);
else //need space for InnerException
builder = new StringBuilder(1200);
builder.AppendLine("Please tell us what you were doing when the problem occurred.\n\n\n");
builder.AppendLine("EXCEPTION DETAILS:");
builder.Append("message:");
builder.AppendLine(err.Message);
builder.AppendLine("");
builder.Append("stack trace:");
builder.AppendLine(err.StackTrace);
if (null != err.InnerException)
{
builder.AppendLine("");
builder.AppendLine("");
builder.AppendLine("inner exception:");
builder.Append("inner exception message:");
builder.AppendLine(err.InnerException.Message);
builder.AppendLine("");
builder.Append("inner exception stack trace:");
builder.AppendLine(err.InnerException.StackTrace);
}
task.Body = builder.ToString();
task.Show();
}
|
2.2. MarketplaceHubTask
The MarketplaceHubTask class launches into the Marketplace Hub. The only parameter is ContentType,
which determines whether the application view or music view of the
Marketplace is displayed. The following is the code to show the music
view:
private void MarketplaceHubTask2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
marketplaceHubTask = new MarketplaceHubTask();
marketplaceHubTask.ContentType = MarketplaceContentType.Music;
marketplaceHubTask.Show();
}
There are no return properties or events. This task
simply shows the marketplace hub, and allows the user to interact with
the hub and then return back to the application by clicking the Back
hardware button.
2.3. MarketplaceSearchTask
The MarketplaceSearchTask also has a ContentType property to filter by either Applications or Music. It also has a SearchTerms property to pass in search terms to kick off the search. The following is the code to kick off search:
private void MarketplaceSearchTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MarketplaceSearchTask marketplaceSearchTask = new MarketplaceSearchTask();
marketplaceSearchTask.ContentType = MarketplaceContentType.Music;
marketplaceSearchTask.SearchTerms = "driving music";
marketplaceSearchTask.Show();
}
Figure 2 shows the task displayed after calling the Show() method.
2.4. MarketplaceDetailTask
The MarketplaceDetailTask class displays the
marketplace details page for an application, which allows you to
purchase the currently running application if it is in trial mode. You
can also show the marketplace details for your other applications so you
can promote them. The property that determines which application to
show details for is the ContentIdentifier property, which is the product ID for the application found in marketplace when an application is certified.
Leave the property null if you wish to display the marketplace details for the currently running application.
|
|
The product ID is generated when an application is
submitted to marketplace, so if you have a family of applications that
you wish to cross-promote, you can simply plug in the product ID for
each application to display the marketplace details page. Here is the
code:
private void MarketplaceDetailTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
marketplaceDetailTask.ContentType = MarketplaceContentType.Applications;
//AppID for the youtube application
marketplaceDetailTask.ContentIdentifier = "dcbb1ac6-a89a-df11-a490-00237de2db9e";
marketplaceDetailTask.Show();
}
2.5. MarketplaceReviewTask
The marketplace review task allows you to display the
marketplace review page for your application from within the
application itself. This is a convenient way to encourage users to
provide a review of your application. This task does not include a ContentIdentifier property, meaning that you can only display the review page for the currently running application. Here is the code:
private void MarketplaceReviewTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MarketplaceReviewTask marketplaceReviewTask = new MarketplaceReviewTask();
marketplaceReviewTask.Show();
}
2.6. MediaPlayerLauncher
The MediaPlayerLauncher class has three properties of interest. The Control's property identifies which media player buttons to display. You can pick MediaPlaybackControls.All for full media controls, or you can use the bitwise "or" operator to combinea custom set of playback controls. The MediaPlayerLauncher has a property named Location that lets the player know how to resolve the URL if the media is located in isolated storage, or as part of the application's xap file. The most important property is the Media property where you set the URL for the media location. Here is code to play a Channel 9 video:
private void MediaPlayerLauncher_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MediaPlayerLauncher mediaPlayerLauncher = new MediaPlayerLauncher();
mediaPlayerLauncher.Controls = MediaPlaybackControls.FastForward |
MediaPlaybackControls.Pause | MediaPlaybackControls.Rewind |
MediaPlaybackControls.Skip | MediaPlaybackControls.Stop;
mediaPlayerLauncher.Location = MediaLocationType.Data;
mediaPlayerLauncher.Media = new Uri("http://files.ch9.ms/ch9/f2c3/b59b6efb-3c70-4bc2-b3ff-9e650007f2c3/wp7ces_high_ch9.mp4");
mediaPlayerLauncher.Show();
}
2.7. PhoneCallTask
The PhoneCallTask class has two properties: DisplayName and PhoneNunber. When the PhoneCallTask.Show() method is called, a dialog box is displayed that says, "Dial DisplayName at PhoneNumber." Here is the code to dial a phone number with the user's consent:
private void PhoneCallTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PhoneCallTask phoneCallTask = new PhoneCallTask();
phoneCallTask.DisplayName = "Rob Cameron";
phoneCallTask.PhoneNumber = "555-555-1111";
phoneCallTask.Show();
}
2.8. SearchTask
The SearchTask class performs the same search as pushing the hardware Search button. It has a SearchQuery property to pass a search string for the search. Here is the code for the SearchTask:
private void SearchTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
SearchTask searchTask = new SearchTask();
searchTask.SearchQuery = "driving music";
searchTask.Show();
}
2.9. SMSComposeTask
The SmsComposeTask class sends an SMS based on the configured properties: the To property and the Body property. Calling the Show()
method brings up the SMS application on the phone with the SMS ready to
go. Note that the user can decide not to send. As with other launchers,
there is no way to determine whether a user cancels or goes through
with the action. Here is the code:
private void SMSComposeTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Microsoft.Phone.Tasks.SmsComposeTask smsComposeTask = new SmsComposeTask();
smsComposeTask.To = "555-555-5555";
smsComposeTask.Body = "Meet me for pizza.";
smsComposeTask.Show();
}
2.10. WebBrowserTask
The WebBrowserTask class opens the full browser experience based on the configured property, URL, which takes a string. Here is the code:
private void WebBrowserTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
WebBrowserTask webBrowserTask = new WebBrowserTask();
webBrowserTask.URL = "http://create.msdn.com";
webBrowserTask.Show();
}
There is a known issue that if you try running this
code under the debugger, it quite often displays the web browser with a
blank URL. Sometimes if you click in the address bar and then click
outside of the address bar, it starts working. Running the code normally
without the debugger seems to work much better.
NOTE
Microsoft announced at Mobile World Conference in
February 2011 that Internet Explorer 9 with support for HTML5 will be
added to Windows Phone 7 later in 2011.
3. Choosers
While the launchers are fire-and-forget, choosers
return information back to the application, such as an image from the
camera, a phone number, or e-mail address. As with the launchers, users
can cancel the action; however, the application will know if the action
was canceled. If the action is not canceled, the information will be
returned to the application with the user's consent.
Choosers have a Show() method like with launchers but choosers also have a Completed event where data is returned. Developers wire-up the Completed event in order to process the returned values.
3.1. CameraCaptureTask
This task allows the user to take a picture. The task
returns a stream to the taken photo. One potential "got'cha" with this
task is that you cannot invoke the camera on a device while syncing with
Zune, because a photo is media, and media interaction is not allowed
while synching with Zune. This is another example of where the WPConnect tool comes in handy. Because the sample is a little more involved, it has its own page for a UI. Listing 2 shows the code.
Example 2. CameraTaskPage.xaml.cs Code File
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
namespace LaunchersAndChoosers.TaskPages
{
public partial class CameraTaskPage : PhoneApplicationPage
{
private CameraCaptureTask cameraTask;
private BitmapImage capturedImage;
string fileName = "capturedimage.jpg";
public CameraTaskPage()
{
InitializeComponent();
cameraTask = new CameraCaptureTask();
capturedImage = new BitmapImage();
cameraTask.Completed += new EventHandler<PhotoResult>(cameraTask_Completed);
PreviewImage.Source = capturedImage;
}
void cameraTask_Completed(object sender, PhotoResult e)
{
if ((null == e.Error) && (null != e.ChosenPhoto))
capturedImage.SetSource(e.ChosenPhoto);
else
{
MessageBox.Show(e.Error.Message);
}
}
private void TakePictureButton_Click(object sender, EventArgs e)
{
cameraTask.Show();
}
private void SavePictureButton_Click(object sender, EventArgs e)
{
WriteableBitmap bmp = new WriteableBitmap(capturedImage);
using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fs =
iso.OpenFile(fileName, System.IO.FileMode.Create))
{
bmp.SaveJpeg(fs, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
savedImage.Source = bmp;
}
}
}
}
}
|
The sample application shows the CameraCaptureTask Chooser to take a picture. Once the user accepts the picture, the image is displayed in the bottom Image
object. When the user clicks the Save Application bar button, the
sample saves the image to isolated storage and displays the image in the
UI in the top Image object.
3.2. EmailAddressChooserTask
The EmailAddressChooserTask class allows the
user to pick an e-mail for an application action, such as sharing a
link or other information in the application. The task shows the phone
UI with a list of contacts to choose once the Show() method is called.
The e-mail address is made available in the Completed event. It could be used as part of launching the EmailComposeTask. Here is the code:
private void EmailAddressChooserTask_MouseLeftButtonDown(object sender,
MouseButtonEventArgs e)
{
EmailAddressChooserTask emailAddressChooserTask = new EmailAddressChooserTask();
emailAddressChooserTask.Completed += new EventHandler<EmailResult>
(emailAddressChooserTask_Completed);
emailAddressChooserTask.Show();
}
void emailAddressChooserTask_Completed(object sender, EmailResult e)
{
if ((null == e.Error) && (TaskResult.OK == e.TaskResult))
{
MessageBox.Show("Email Address Returned is: " + e.Email);
}
}
3.3. PhoneNumberChooserTask
The PhoneNumberChooserTask class allows the user to pick a phone number for an application action, such as to open the PhoneCallTask launcher. The task shows the phone UI with a list of contacts to choose once the Show() method is called. The phone number is made available in the Completed event. Here is the code:
private void PhoneNumberChooserTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PhoneNumberChooserTask phoneNumberChooserTask = new PhoneNumberChooserTask();
phoneNumberChooserTask.Completed += new EventHandler<PhoneNumberResult>
(phoneNumberChooserTask_Completed);
phoneNumberChooserTask.Show();
}
void phoneNumberChooserTask_Completed(object sender, PhoneNumberResult e)
{
if ((null == e.Error) && (TaskResult.OK == e.TaskResult))
{
MessageBox.Show("Phone number returned is: " + e.PhoneNumber);
}
}
3.4. PhotoChooserTask
The PhotoChooserTask class is very similar to the CameraCaptureTask, in that it returns a photo image. The PhotoChooserTask has a property named ShowCamera
to give the user an option of choosing an existing photo or capturing a
new photo. After calling the Show() method to launch the UI, the Completed event fires when the user is done, and the picture is loaded into an Image control in the UI. Here is the code:
private void PhotoChooserTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PhotoChooserTask photoChoserTask = new PhotoChooserTask();
photoChoserTask.ShowCamera = true;
photoChoserTask.Completed += new EventHandler<PhotoResult>(photoChoserTask_Completed);
photoChoserTask.Show();
}
private BitmapImage capturedImage;
void photoChoserTask_Completed(object sender, PhotoResult e)
{
if ((null == e.Error) && (TaskResult.OK == e.TaskResult))
{
capturedImage = new BitmapImage();
capturedImage.SetSource(e.ChosenPhoto);
ChosenPhotoImage.Source = capturedImage;
}
}
3.5. SaveEmailAddressTask
The SaveEmailAddressTask class shows the
built-in contacts application. It allows the code to save the provided
e-mail address to a new or existing contact via the Email property. Use the Completed event to determine whether an error occurred and that the task completed successfully. Here is the code:
private void SaveEmailAdressTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
SaveEmailAddressTask saveEmailAddressTask = new SaveEmailAddressTask();
saveEmailAddressTask.Completed += new EventHandler<TaskEventArgs>
(saveEmailAddressTask_Completed);
saveEmailAddressTask.Email = "[email protected]";
MessageBox.Show("Saving this email: " + saveEmailAddressTask.Email);
saveEmailAddressTask.Show();
}
void saveEmailAddressTask_Completed(object sender, TaskEventArgs e)
{
if ((null == e.Error) && (TaskResult.OK == e.TaskResult))
{
MessageBox.Show("Email address saved");
}
}
3.6. SavePhoneNumberTask
The SavePhoneNumberTask works very similarly to the
SaveEmailAddressTask, except that it passes in a phone number instead of
an e-mail address. Here is the code:
private void SavePhoneNumberTask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
SavePhoneNumberTask savePhoneNumberTask = new SavePhoneNumberTask();
savePhoneNumberTask.Completed += new EventHandler<TaskEventArgs>
(savePhoneNumberTask_Completed);
savePhoneNumberTask.PhoneNumber = "555-555-5555";
MessageBox.Show("Saving this phone number: " + savePhoneNumberTask.PhoneNumber);
savePhoneNumberTask.Show();
}
void savePhoneNumberTask_Completed(object sender, TaskEventArgs e)
{
if ((null == e.Error) && (TaskResult.OK == e.TaskResult))
{
MessageBox.Show("Phone number saved");
}
}