Problem: Background Images in secondary tiles do not appear if using remote images.
Solution:
<wp:BackgroundImage> and <wp:BackBackgroundImage> can use remote URLs, however, the domains need to be included in the Approved URLS list. For example:
// Lists domains that can send tile updates and so forth as push notifications.
// Only these authorized domains will be allowed by the shell to push new tiles to the phone
var ListOfAllowedDomains = new Collection<Uri> {
new Uri(@"http://i. contoso.com"), new Uri(@"http://i-staging.contoso.com") // e.g. if you published a webservice at http://foo.com/service1.svc -- put "http://foo.com" here.
};
pushChannel.BindToShellTile(ListOfAllowedDomains);
By including the domains in the ‘allowed list’ your background images will show up.
Thanks,
Mike
The following is a collection of FAQs regarding Windows Phone Push Notifications.
Q: How can I get started with Push Notifications?
A: A good way to approach Push Notifications is using a known working sample. Entire sample including client and server code here. Once you get the sample working, you can transfer that to an actual application. This way you can be sure you are composing the push notifications correctly. I would they suggest they get the sample working and then compare that to how they are doing the same notification type.
Q: Do we have to get a new URI if the original URI was received more than 30 days ago?
A: No. As long as the URI has not changed, you can continue to use the URI.
Q: How do we know if the URI has changed?
A: When the app starts, do an HttpNotificationChannel.Find and compare to the previously received channelURI stored in isolated storage. If different, update the web service registration with the new channelUri. If empty, recreate the Channel. See the file MainPage.xaml.cs in the sample here where this logic has been implemented. Note that it is a best practice to send along with the URI information that uniquely identifies the device (DeviceExtendedProperties.GetValue("DeviceUniqueId"). You can use this information when re-registering channel URIs with your web service to replace the existing (invalid) URI with the new one.
Q: How can we tell at the web service if the URI we are sending to the MPNS is still valid?
A: The MPNS will return a 404 response code with one the following notification statuses if the URI is not valid:
| Response Code | NotificationStatus | DeviceConnectionStatus | SubscriptionStatus |
| 404 Not Found | Dropped | Connected | Expired |
| 404 Not Found | Dropped | Temporarily Disconnected | Expired |
| 404 Not Found | Dropped | Disconnected | Expired |
Note that your web service should stop sending notifications to this URI and un-register it, if the MPNS returns 404 (Dropped).
Q: What causes the MPNS to return the 404 (expired) response code?
A: A URI will become invalid if two consecutive notification requests within 30 days return the 412 (inactive) response code. When the application restarts it will receive a new channel URI, which should replace the current (expired) channel URI registered with the web service.
Q: What causes the MPNS to return the 412 (inactive) response code?
A: If the device has been off or otherwise cannot connect with the MPNS it is considered 'temporarily disconnected'. When the device is in this state, the MPNS will return:
| Response Code | NotificationStatus | DeviceConnectionStatus | SubscriptionStatus |
| 200 OK | Received | Temporarily Disconnected | Active |
If the web service sends another notification to this URI and at least 90 minutes have passed since the last 'temporarily disconnected' notification, MPNS flags the URI ‘inactive’ and will return the 412 response code. In this state, MPNS stops attempting to connect to the device. Note that temp disconnected and inactive are both natural states for a mobile device and shouldn’t be viewed negatively. Commonly 30-40% of devices show temp disconnected at any one time and 10-20% show inactive because mobile devices transition between network conditions and situations frequently.
Q: If the PNS is no longer attempting to connect to the device, when does it start communicating again?
A: The PNS will attempt to connect to the device when the Web Service sends the next notification request. The response code returned reflects the devices state (200 – URI OK, 404, URI invalid, 412, URI OK, Device out of communication)
Q: What does the PNS response code 200 suppressed mean?
A: You can receive the suppressed status when for a:
- Tile notification if the user hasn't pinned the tile
- Raw when the app is not in the foreground
- Toast and Tile when the device is in low battery state
Q) What is the limit of notifications I can send to the users of my app?
A) By default, the limit is 500 notifications per channel URI per day. So if you have multiple notifications (say Toast and Tile) in your application, you can send 500 of each type. That is 500 of each type of notification per device / user. For example, if you have 100 users of your application and 1 type of notification, you can send up to 50,000 (1 * 500 * 100) notifications per day. Authenticated notifications are unlimited.
Q) How do I setup authenticated notifications?
A) Follow the guidance here: Setting Up an Authenticated Web Service to Send Push Notifications. Pay particular attention to the set up the the certificate.
Q) What can cause a 401 (Unauthorized) status returned when attempting to send an authenticated notification?
A) Can can get a 401 if the Service Name in the certificate does not match the service name parameter in the HttpNotificationChannel constructor. Also, the client will receive a URI with an ‘http’ prefix. If functioning properly HttpNotificationChannel will return a Uri with an ‘https’ prefix.
Q) I am setting up authenticated notifications and am getting back a 403 status code in my web service code. What is going wrong?
A) Generally, a 403 (forbidden) status is what you would get if either you are not including a certificate in the POST request or it is not a valid/trusted cert. Note that the certificates need to be deployed onto the web servers sending the requests. These certificates should include the private key. (The certificate uploaded to Microsoft should NOT include the private key.) If using an intermediate certificate, ALL of the certificates in the chain should be added prior to the POST request (see below). When submitting your application to Marketplace, you will also need to associate your application with the appropriate certificate. This is done in the ‘describe’ step:
Q) How do I include a certificate(s) in the POST request?
A) If you are using .NET in your server code, you can add the certificate to the HttpWebRequest as follows:
Request.ClientCertificates.Add(new X509Certificate2("[PathToCertificate]", "[Password]"));
Q) What can cause a 409 to be returned from the MPNS?
A) A 409 is returned when using authenticated notifications and the certificate has expired. You will need to submit a new certificate.
The following is a summary of some of the performance measurement tools available from Microsoft for Windows Phone applications.
Marketplace Test Kit – Automated tests for peak memory usage, launch time, app closure, and back button.
These tests are part of the Windows Phone 7.1 SDK. To launch the tools, right click on your project in Visual Studio and select ‘Open Marketplace Test Kit’.
| Test Name | Test Description |
| Launch time | Validation of application launch time. |
| Peak memory consumption | Validation of application peak memory consumption |
| Application closure | Validation of all exceptions being handled and application not closing unexpectedly. |
| Use of Back Button | Validation of proper behavior when pressing the Back button. |
Frame Rate Counters for Drawing Performance
To enable:
Application.Current.Host.Settings.EnableFrameRateCounter = true;
Microsoft.Phone.Shell.SystemTray.IsVisible = false; // System Tray not visible

Render Thread FPS: The number of frames per second that the independent simple animations and rendering thread is using. Keeping around 60 will provide a great experience, while a number of 30 fps will begin to show a poor experience to the end user.
Under 30 fps this counter will turn red in post-beta builds.
User Interface Thread FPS: The number of fps that the primary user interface thread is experiencing. Property change notifications, data binding, primary managed code execution, and animations not handled on the render thread use this threads’ resources.
Turns red when the count is at or below 15 fps.
Texture Memory Usage: A specialized memory counter indicating the video memory used for storing application textures.
Surface Counter: A count of the number of surfaces that are passed to the graphics chip.
Intermediate Texture Count: The number of intermediate textures created for compositing.
Screen Fill Rate: A metric representing the number of complete phone screens being painted each and every frame.
Memory APIs for measuring / logging memory usage
long applicationCurrentMemoryUsage =
(long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
long applicationPeakMemoryUsage =
(long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
Thanks,
Mike

Todd Brix gives a summary here of the new features included in the App Hub Update that went live on July 18th. In this post I’ll review a couple of the new features and tips for using them.
Previously you provided the application name in the description step (step 2) See screenshot below. You needed to specify this for each language your application supported. (See below.)

Now with the App Hub update, the application name is derived from the Title attribute of the App element in WMAppManifest.xml:
<App xmlns="" ProductID="{xxx5d2d6-ebb1-4e5b-bd12-7e1371696e80}" Title="People and Places"
RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"
Author="Mike Francis" Description="" Publisher="Mike Francis">
This is great improvement since now the application title is maintained in one place: your application. See this blog post for information on localizing the application title. App Hub will automatically retrieve the appropriate localized application title for each supported language. See here for a sample project with this implemented. Try creating a test submission (you can delete it later) and upload the resulting XAP file from the sample. Note how App Hub is creating a language version for each language supported. Also note how the localized application name is automatically populated.

As stated in this forum post, the App Hub now requires a default language specified in your application. This is the ‘Neutral Language’ assembly setting in Project settings.
- Right Click on your project in Solution Explorer
- Application | Assembly Information. . .
- Neutral Language
- Pick a specific default language. For example for English:
In the ‘Describe’ section (step 2) of your application submission, you provide the screenshots and icons that are used by the PC and Phone versions of Marketplace. Another nice AppHub feature is the ability to upload all of the artwork at once. You can do this as long as you have the art work in the same directory. For my application, I have created a directory <Project Name>\Images\Marketplace and placed my icons and screenshots there. Then when submitting my app, in the ‘Artwork’ section of step 2, I click ‘Browse”, and multi-select all of the artwork in this folder. App Hub intelligently associates the correct size icon with the corresponding App Hub icon slot. See video below.
App Hub: One click application art upload
Tip: This feature reads the screenshot images in alphabetical order, so if you care about the order of your screenshots, rename them so that the filenames are in alpha-order. This way when the tool reads in your screenshots, they will be in the order you expect. For example, (1ScreenShot.png, 1ScreenShot.png, etc.)

Thanks,
Mike

The Coding4Fun library (http://coding4fun.codeplex.com) for Windows Phone 7 includes many super useful classes that will save you time when writing Windows Phone 7 applications. My favorite is their implementation of very the professional looking and easily extensible user prompts.
While a good assortment of prompts, utilities and other controls have been implemented in coding4fun, what is missing is a login prompt. In this post I’ll review how I’ve used Coding4Fun to create a login prompt.
Can’t I just use a login page?
Many developers have struggled with the Microsoft enforced application navigation flow that mandates:
1) Pressing the Back button must return the application to the previous page or return to any previous page within the back stack.
2) Pressing the Back button from the first screen of an application must close the application.
These rules are difficult to reconcile with an application that has a login prompt on the first page. A couple of problems with this:
1) After the user has successfully logged in, and they have navigated away from the login page, it is confusing if pressing BACK returns them to the Login screen. The expectation is that once they have logged in they should not see the login screen again.
2) Even if you structure the program to navigate to the Login page automatically from the main page if the user has not yet logged in, this gets rid of the ‘BACK navigates to the Login screen’ problem, but it violates the first rule above where BACK on the first screen should exit the app.
See Peter Torr’s article, Introducing the concept of “Places”, for a way to think of ‘places’ and ‘transient UI’. In Peter's article, he recommends one way to handle the login scenario is with the use of a popup. Enter Coding4Fun.
How It Works
The Coding4Fun’s MessagePrompt class, includes a Body property that you can use to add code on the fly. For example:
messagePrompt.Body = new TextBlock { Text = "Hello World!", Foreground = new SolidColorBrush(Colors.Green),
FontSize = 30.0}
I extended this idea to include, a user control ‘LoginUserControl’ which contains the XAML layout and Username and Password members which are databound to the user control.
In the code below I instantiate the LoginUserControl control, add it to the Body member of an instance of MessagePrompt, display the prompt, and process the user results.
private void Button_Click(object sender, RoutedEventArgs e)
{
var luc = new LoginUserControl(); // Customer user control with Login UI
MessagePrompt messagePrompt = new MessagePrompt(); // Coding4Fun extensible MessagePrompt
messagePrompt.IsCancelVisible = true; // Show cancel button
messagePrompt.Body = luc; // Add user control as body of MessagePrompt
messagePrompt.Completed += (str, res)=> // Handler for MessagePrompt user action
{
if (res.PopUpResult == PopUpResult.Cancelled)
{
luc.Username = luc.Password = "";
MessageBox.Show("Login Cancelled");
}
else
{
MessageBox.Show(string.Format("Username: {0}, Password: {1}", luc.Username, luc.Password));
}
};
messagePrompt.Show();
}
You can download the sample code here.
Mike
A couple developers I have been working with have had a problem with their application crashing during certification testing, or their app not working as expected after being published. This problem was difficult to debug since the app worked fine for the developer, but would crash out of the gate during testing. After some investigation, we found that the developer was relying on the Product ID to be a known value.
The Product ID is a GUID used to identify your application in the Windows Phone installed application list. This value stays the same across application updates. The Product ID is not controlled by the developer, but is assigned during the ingestion process. That is, the value created by Visual Studio and stored in WMAppManifest.xml, is not the value that will be used when the application is published.
If you are relying on the Product ID to be a certain value – it won’t be what you expect, when your application is published.
<App xmlns=""
ProductID="{eb186f6f-78ab-49d2-937d-daa5d0cb7889}"
Title="BestAppEver" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"
Author="BestAppEver author" Description="Sample description" Publisher="Cookie1">
Here are a couple of workarounds to consider:
- Instead of using the Product ID, use a private scheme to store the unique value your app needs.
- If your really need to use the Product ID, you can leverage the way App Hub works. That is, the Product ID is assigned early on in the submission process. Specifically, in Step 1 when you upload your app. You can upload a preliminary version of your app and not submit it for testing. You can then use this Product ID in your code. When your application is ready for submission, you can re-upload your app, overwriting the preliminary version with the final version. The Product ID will not change. See below for sample code on how to read the Product ID at run-time.
To see the Product ID as assigned by Product ID, in your “my apps” list on the dashboard, click on the name of your submission.

Here, you can see the Product ID and the Deep Link. This will not change for this submission.
Code to read the Product ID at run time:
public static string GetProductId()
{
System.Xml.Linq.XElement xml = System.Xml.Linq.XElement.Load("WMAppManifest.xml");
var appElement = (from manifest in xml.Descendants("App") select manifest).SingleOrDefault();
if (appElement != null) {
return appElement.Attribute("ProductID").Value;
}
return string.Empty;
}
Mike
To submit your app to Marketplace for distribution, you will need an App Hub Account. Open one at: http://create.msdn.com
Opening an account is also necessary to developer unlock your Windows Phone 7 hardware.
Tip: Make sure you use an international credit card if opening an account outside of the US.
Tip: If you will use this account for a company, do not use a personal Windows Live ID when creating the account. You don’t want to mix your personal account details with your company’s and after you create the account, you can’t change the Windows Live ID.
For a guide of the Windows Phone 7 registration process, see here.
For a guide of the Windows Phone 7 Marketplace application submission process, see here.
To help teams track their progress in meeting the Windows Phone 7 certification requirements, I’ve created the following guide. I have used this myself when reviewing partners applications prior to submitting to Marketplace. Please see the instructions on the first tab.

Instructions

Sample Page
Thanks,
Mike
There are a couple of ways to go about detecting Tap and Hold in Windows Phone 7. This method uses the XNA Touch Gesture recognizer (Microsoft.Xna.Framework.Input.Touch) in a Silverlight application. The touch gesture recognizer can tell the difference between tap, double-tap, and hold gestures. Additionally, using the XNA gesture recognizer you don’t need to worry about mistaking a pan/drag for a hold: if you move your finger too much, a tap or hold won’t be recognized. Other solutions involve inferring these events through the use of a timer. A common application of this is to implement a context menu in your Windows Phone 7 application.
This method handles the ManipulationStarted event to detect the initial tap. In this event, you tell the gesture recognizer which gestures you want to monitor. In this case, tap, double-tap, and hold. (This is also done in the constructor of the page, to initialize the recognizer.)
Next a 500 ms timer is started. The timer is used to detect when enough ‘hold time’ has elapsed. When the ‘hold time’ threshold is met, the gesture is detected, the gesture recognizer is reset, and the timer is stopped. This is where you would invoke the context menu. (Not implemented here.) A timer is only necessary here for the implementation of a context-menu. You could detect the gesture in the ManipulationCompleted event handler, which fires when the user releases their finger from the screen.
- public MainPage()
- {
- InitializeComponent();
- TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Hold | GestureType.DoubleTap;
- }
-
- System.Windows.Threading.DispatcherTimer dt;
- public void StartHoldTimer()
- {
- dt = new System.Windows.Threading.DispatcherTimer();
- dt.Interval = new TimeSpan(0, 0, 0, 0, 500);// 500 Milliseconds
- dt.Tick += new EventHandler(dt_Tick);
- dt.Start();
- }
-
- int cnt = 0;
- void dt_Tick(object sender, EventArgs e)
- {
- if (cnt == 3) // 500 ms * 4 == 2 seconds
- {
- cnt = 0;
- GetGesture();
- // disable all events
- TouchPanel.EnabledGestures = GestureType.None;
- // stop the hold timer
- StopHoldTimer();
- }
- cnt++;
- }
-
- void StopHoldTimer()
- {
- dt.Stop();
- cnt = 0;
- }
-
- private void GetGesture()
- {
- if (TouchPanel.IsGestureAvailable)
- {
- GestureSample gs = TouchPanel.ReadGesture();
- if (gs.GestureType == GestureType.Hold)
- {
- string gestureString = string.Format("{0}: {1}", gs.GestureType, gs.Position);
- // Tap and Hold detected, report position
- Debug.WriteLine(gestureString);
- }
- }
- }
-
- private void PhoneApplicationPage_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
- {
- // specify what events the XNA gesture recognizer will look out for
- TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Hold | GestureType.DoubleTap;
- // start the hold timer
- StartHoldTimer();
- }
-
- private void PhoneApplicationPage_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
- {
- // disable all events
- TouchPanel.EnabledGestures = GestureType.None;
- // stop the hold timer
- StopHoldTimer();
- }
Enjoy!
Mike
This sample code uses the IsolatedStorageFile class to create a few test directories and populates them with files. Then it recursively enumerates the files and directories, displaying the output in the debug window.
- public void EnumerateIsolatedStorageFiles()
- {
- try
- {
- // Get an isolated store for this applicaiton and put it into an
- // IsolatedStorageFile object.
-
- using (IsolatedStorageFile isoStore =
- IsolatedStorageFile.GetUserStoreForApplication())
- {
- // Create sub directories and create files
- // in them to test enumeration
- isoStore.CreateDirectory("A");
- IsolatedStorageFileStream streamA =
- new IsolatedStorageFileStream(@"A\TestFileA.Txt", FileMode.Create, isoStore);
-
- isoStore.CreateDirectory("B");
- IsolatedStorageFileStream streamB =
- new IsolatedStorageFileStream(@"B\TestFileB.Txt", FileMode.Create, isoStore);
-
- isoStore.CreateDirectory("C");
- IsolatedStorageFileStream streamC =
- new IsolatedStorageFileStream(@"C\TestFileC.Txt", FileMode.Create, isoStore);
-
- isoStore.CreateDirectory(@"C\1");
- IsolatedStorageFileStream streamC1 =
- new IsolatedStorageFileStream(@"C\1\TestFileC1.Txt", FileMode.Create, isoStore);
-
- isoStore.CreateDirectory(@"D\1\2\3\4\5");
- IsolatedStorageFileStream streamD =
- new IsolatedStorageFileStream(@"D\1\2\3\4\5\TestFileD.Txt", FileMode.Create, isoStore);
-
- streamA.Close();
- streamB.Close();
- streamC.Close();
- streamC1.Close();
- streamD.Close();
-
- // There might be a small delay between when the above code
- // executes and when the files are created in the store.
- // Closing and opening the store in this example ensures that
- // the common language runtime has finished creating the files.
- } // using
-
- using (IsolatedStorageFile isoStore =
- IsolatedStorageFile.GetUserStoreForApplication())
- {
- // List files in root
- foreach (string file in isoStore.GetFileNames())
- {
- Debug.WriteLine(file);
- }
- // Recursively enumerate sub-directories and list contents
- GetFiles(isoStore, @"\");
- } // using
- }
- catch (IsolatedStorageException e)
- {
- Debug.WriteLine(e.Message);
- }
- }
-
- // Recursively enumerate sub-directories
- void GetFiles(IsolatedStorageFile isoStore, string directory)
- {
- string[] DirNames;
- if (directory == @"\")
- DirNames = isoStore.GetDirectoryNames();
- else
- DirNames = isoStore.GetDirectoryNames(directory + @"\*");
-
- foreach (string dir in DirNames)
- {
- string mDir =
- directory == @"\" ? directory + dir : directory + @"\" + dir;
- foreach (string file in isoStore.GetFileNames(mDir + @"\*.*"))
- {
- Debug.WriteLine(file);
- }
- GetFiles(isoStore, mDir);
- }
- }
Enjoy!
Mike

One of my favorite Windows Mobile applications has been Bing (the application formerly known as “Live Search”). This application has saved my bacon on more than one occasion when travelling on business or vacation. The ability to search for vital resources, wherever I am, like the closest Starbucks has been invaluable to me.
While Live Search was great, the UI was a little clunky and was not developed with capacitive screens and the corresponding touch navigation in-mind. Capacitive screens while more sensitive to touch, have a larger minimum hit target size. Actually comparing Live Search to the new Bing is a good example of how an application designed for a resistive screen has been updated to also work with capacitive screens.
The usability has greatly improved. For example to starting navigating to the nearest Starbucks, you:
- From the Bing home page, Tap ‘Speak’ and say ‘Starbucks’
- Select the ‘Starbucks’ you want to go to
- Tap the Car icon for driving directions
- Tap on ‘Navigate’ (If you are on foot, select the ‘Walk’ tab for walking directions.)
Immediately a route is calculated for you and Silicon Sally is telling you where to go. Yes ‘telling you’, with voice directions! This is a huge improvement over Live Search that had text only turn-by-turn directions. In the Bing settings, you can specify if you want to route via the shortest or fastest route. You can also configure Bing to consider real-time traffic conditions when calculating your route.
Now featuring ‘auto-rerouting’! Live Search would prompt you will a demoralizing ‘Are you lost? Would you like to reroute from here?’ prompt whenever you deviated from your planned route. Bing for mobile smartly just tells you that it is ‘rerouting’ and updates your driving directions based on your current location.
All the great features of Live Search are still here like quick access to locally playing movies and show times.
You can install Bing for mobile from the Marketplace for Windows Phone here.
More information here.
Enjoy!
Mike