Scott Hanselman

Updating my Windows Phone App to Windows Phone 8

December 8, '12 Comments [18] Posted in WinPhone
Sponsored By

Lost Phone Screen on Windows Phone 8Earlier this year I wrote a small Windows Phone 7 application in a day called Lost Phone Screen. It creates lock screens for you with your name and contact number on them to aid in finding your phone the old fashioned way when you lose it. No need for a GPS, just tell folks you have a small reward and give them a number to call. You can download it free now as folks will not pay 99 cents for anything except Angry Birds. But I'm not bitter. ;) Anyway, it works great on Windows Phone 7 and Windows Phone 7.5 (Mango.)

Recently I got a Nokia Lumia 920 with Windows Phone 8 and since there's a number of new APIs and features I could exploit - not the least of which being the ability to programmatically set the phone's Lock Screen without the user needing to do anything - I figured it was time to update it.

I encourage you to review the post From Concept to Code in 6 hours: Shipping my first Windows Phone App as a reminder of what the app did and the issues I had writing the Windows Phone 7.x version.

Here's what I had to think about updating the app for Windows Phone 8. Big thanks to my friend Justin Angel at Nokia for brainstorming on Skype with me and helping with the async code and resolution issues. His blog post on What's New in Windows Phone 8 was very useful, especially his little MultiRes helper class.

Updating The App

First, to be clear, the existing Windows Phone 7 app works great on Windows Phone 8 without ANY changes. It runs and behaves exactly on Windows Phone 8 as it did on Windows Phone 7. I wanted to update it in order to "light up" some the new features on the new OS.

Upgrading the Project to Windows Phone 8

Upgrading was easy, I opened the old project and was prompted to upgrade. I double-clicked on the WMAppManifest.xml and made sure to reassert some of the basic settings like icon sizes and tiles for my app, as well as confirming the capabilities that my app would need like photo access, etc.

I was sure to check the Supported Resolutions as I knew I'd need those later.

Windows Phone 8 supports three resolutions

Keeping two Branches vs. One Super Project

I went back and forth on this. It's an upgraded OS but 99% of the code will be shared. However, enough stuff has changed that I decided to make a branch in source control rather than make a single build. Honestly, there's likely no wrong answer here and you use what you're comfortable with. I could have to CSProj files if I liked, or just made a different Build Configuration (like Debug8 and Debug7, etc) but I understand my source control pretty well so I ended up with a phone70 and a phone80 branch and I switch between them. It's more likely that I'll be updating the phone80 branch then "back porting" new feature so for now this work fine, but know I can always make a single build if I want.

Ultimately though, I know that I need to make a build for Windows Phone 7.x and one for Windows Phone 8 but I can submit them each to the Store under the same name and the Store will do the right thing. If you've got Windows Phone 8 with a new resolution you'll get the right version as you can see in the screenshot below. I've submitted two XAP files.

Two versions of the same app in the Store, one for each phone

New Screen Resolutions

I updated my app a few weeks ago but my first good bug came in from a gent with a HTC Windows Phone device running at 1280x720, rather than 1280x768. He said my lockscreens were cropped! With Windows Phone 8 there's three resolutions, in fact as Justin points out:

The resolutions are: WVGA (480x800 pixels), also used in Windows Phone 7; WXGA (768x1280 pixels), essentially an HD version of WVGA; and the wildcard 720P (720x1280 pixels) that uses a different aspect ratio to WVGA and WXGA. You should be aware of these different resolutions, make sure to use relative <Grid /> positioning in laying out screens, and potentially different media assets for different resolutions.

It's less important that there's three resolutions but rather more interesting that 720p is a different aspect ratio! Turns out I was making a number of assumptions in my code, not the least of which being the screen resolution. I was assuming 15:9 as the aspect ratio like 800x480 and 1280x768, but 16:9 is 1280x720!

My initial reaction was, crap, now I have to actually think.

Turns out that it's easier than that. On all of my app's pages but one I was able to remove XAML code and hard coded margins and row definitions. I was actually being too specific and not letting the system lay itself out optimally.

I removed all my hard-coded margins and changed my Grids to use a RowDefinition of "*" which means "the rest of the space" like this:

<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
...
</Grid>

The first RowDefinition fills to the size of its content and the second just takes up the rest. This made all my pages look great on every resolution screen, and it was easy to test because I could just change the Emulator dropdown to select the various  resolutions:

Different Emulator Resolutions in a Dropdown

However, with these new resolutions, I did change my originally single SplashScreenImage.jpg to include one each for the three resolutions named SplashScreenImage.Screen-720p.jpg, SplashScreenImage.Screen-WVGA.jpg and SplashScreenImage.Screen-WXGA.jpg. You'll find that at least half your time doing mobile apps (regardless of Apple, Windows or Android) is getting the PNGs and artwork files correct).

Three new SplashScreens

I had (chose) to hard code some screen sizes in one place in the app. (I could have queried  Application.Current.Host.Content.ScaleFactor. Application.Current.Host.Content.ActualHeight and Application.Current.Host.Content.ActualWidth to be correct.) I have a VERY specific custom Image Cropping control that needed special handling for the 720p case, likely due to my lack of skill with XAML. I am told that only the most edgy of edge cases need to do this and often this is in the creation of pixel-perfect lock screens so you probably won't sweat it at all.

New Lock Screen API

Finally my app can update the Lock Screen without manual user intervention. This was my #1 request and everyone assumed it was my fault that the feature didn't exist. It's been added in Windows Phone 8.

If you app wants to change the Lock Screen it has to ask once and get permission. It has to be the "current lock screen provider." If it is, it requests access and then sets the lock screen.

if (!LockScreenManager.IsProvidedByCurrentApplication)
{
LockScreenRequestResult result = await LockScreenManager.RequestAccessAsync();
if (result == LockScreenRequestResult.Granted)
{
SetAsWallpaper(filename);
}
}
else
{
SetAsWallpaper(filename);
}

SetAsWallpaper is just a helper around LockScreen.SetImageUri().

private void SetAsWallpaper(string filename)
{
string realPath = "ms-appdata:///local/" + filename;
Debug.WriteLine(realPath);
//Debug.WriteLine(ApplicationData.Current.LocalFolder.Path);

LockScreen.SetImageUri(new Uri(realPath, UriKind.Absolute));
}

And that's it. Lovely and simple. BUT.

A Very Important Reminder when using Asynchronous APIs

In Windows 8 and Windows Phone 8 (since the Windows 8 magic dust is under Windows Phone 8) everything is all about asynchrony and non-blocking APIs. Before I'd just save the wallpaper and you'd wait and you had no choice. Now all the underlying APIs are asynchronous  (non-blocking) and we as developers have await/async keywords to make things simple, right?

Sure, but my second lovely bug that showed up was when folks mashed on the Save button many times. Because everything is non-blocking this would fire off many save requests and eventually they'd collide at the file system with an "Access Denied" or something equally useful.

I have this shared resource that I need to protect access to but I don't want to block the UI. Michael L Perry has a great solution for this that should probably be built into the Windows Phone SDK (unless it is and we've all missed it?) in his Awaitable Critical Section helper. This helper lets us use the familiar using{} block structure in situations where we are using async and await inside what would have been a lock(){} block.

As Michael points out, you CAN'T do this because you can't await in a lock.

lock (this)
{
FileHandle file = await FileHandle.OpenAsync();
await file.WriteAsync(value);
file.Close();
}

But with his helper you can do this:

using (var section = await _criticalSection.EnterAsync())
{
FileHandle file = await FileHandle.OpenAsync();
await file.WriteAsync(value);
file.Close();
}

And I did just that.

Analyze

When you're done, make sure you run the Windows Phone Application Analysis tools see how your application does. Does it use too much memory? Use up the battery? Does it startup in less than a second?

Windows Phone Application Analysis

This is fascinating stuff. Don't work so hard on your app and forget to profile it.

New Things to Remember when Submitting Your App and Submitting Two Versions

I fixed some bugs in the Windows Phone 7 version, changed that XAP's version number and submitted it as a small upgrade. Folks who have Windows Phone 7.x will get prompted to update their app. This version, as you'll recall, doesn't auto-update the lock screen because it can't.

I go into the Phone Marketplace and click Update App from the Dashboard. There's the Marketplace before my update, showing the 7.1 app:

Windows Phone 7 app

I click Update selected and upload the new Windows Phone 7.1 targeted XAP that I just built. After that's uploaded I change the dropdown and upload the Windows Phone 8 XAP. I make sure in both cases to upload a Release XAP and the "AnyCPU" version.

Windows Phone 8 app

I am keeping the Windows Phone 8 one a few versions ahead for my own sanity. It makes sense to me and it helps me remember what's "newest" even though it only matters that the new versions be higher than the previous versions.

Be sure to check all your text, your descriptions and icons to make sure they are correct.

Time Spend Coding vs. Time Spend Editing PNGs

Goodness, I swear I have spent more time messing with screenshots and PNGs than coding.

Here's the thing: Mobile app development is all about the Screenshots and Icons.

There's so many resolutions and assets and different scenarios where your application can be showcased that it's worth spending some time getting really good at PhotoShop or Paint.NET. I'm doing all my work in Paint.NET, in fact.

Because there's three resolutions you'll want to make note that you need three sets of screenshots! Fortunately there's a screenshot cool built into the Emulator and Windows Phone also supports in-device screenshots (finally) by pressing Power+Windows Key.

It may not be obvious from this picture of the marketplace submission but you need to click WXGA and 720p and upload separate screenshots for each one! Otherwise your potential users won't see your app looking exactly as it will on their device. Tedious, but crucial.

Three sets of screenshots for three resolutions

Truly, this became an asset management chore. I ended up with a folder fill of JPGs and PNGs and only kept my sanity with some reasonable file name conventions.

naming screenshots and splashscreens reasonably.

You will end up with at least 24 screenshots (3x8) plus three splash screens, several icon sizes and you'll also want to test on both the Dark and Light themes.

Conclusion

In the end, it will be seamless for your end users. Folks who have Windows Phone 8 will get their updates from your WP8-XAP and Windows Phone 7.x folks will get theirs from your WP7-built XAP. This whole thing took about 3 hours and most of that time was spent doing screenshots.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Saturday, December 08, 2012 1:21:17 AM UTC
Also, if you have your app localized, multiply 24 screenshots to the number of localizations ;)
Sergey
Saturday, December 08, 2012 1:22:49 AM UTC
Wow! I need an intern! ;)
Saturday, December 08, 2012 2:25:39 AM UTC
The SemaphoreSlim class was updated on .NET 4.5 (and Windows Phone 8) to support async waits. You would have to build your own IDisposable Release, though. (In the situation you describe, I usually just disable the button at the beginning of the async handler and re-enable it at the end; but async synchronization would work too).

If you need other async-ready primitives, Stephen Toub has a blog series on the subject and I've implemented them in my AsyncEx library (which supports both Windows Phone 8 and Windows Phone 7.5).
Saturday, December 08, 2012 4:15:59 AM UTC
Awesome. And you can do it all over again when MS changes the API yet again in 20s.
David
Saturday, December 08, 2012 6:01:57 PM UTC
Why does this app use almost 40MB of RAM? Is it because of all of the various PNGs that are embedded or something? Even the average usage of 22MB seems excessive.
Coleman
Sunday, December 09, 2012 4:01:19 AM UTC
Some time back, someone ported your BabySmash to Windows Phone 7 (calling it SmashItBaby). Unfortunately, it was a buggy port that crashed after a while.

Would you consider porting BabySmash to Wp7/8?
Mike C
Sunday, December 09, 2012 12:37:10 PM UTC
Hey Scott, any chance you will review the phone?
Sunday, December 09, 2012 10:28:45 PM UTC
Speaking of lock screens are you aware of a bug on the WP8, where the phone autolocks during an active phone call but you cannot 'unlock' the phone till the current active phone has ended. So you cannot multi task like you can on the the iPhone or the Android phones?

http://windowsphone.uservoice.com/forums/101801-feature-suggestions/suggestions/3406467-call-screen-lock-button-bug-
Monday, December 10, 2012 1:29:35 PM UTC
Thanks, I didn't know about your app. Installed it on my Windows 7 phone... as I'm prone to losing stuff.
Andre du Plessis
Monday, December 10, 2012 2:21:15 PM UTC
I realize the point of this article is to show an example of porting an app from the old Windows Phone to Windows 8 Phone, but I just wanted to point out to people that didn't know that Windows 8 actually comes in with this functionality built in - I bet they stole Scott's idea! ;-)

You just go to Microsoft's windowsphone.com, log in with your Microsoft Account and you can not only lock your phone with a custom message you enter, but you can ring it -- in case you've lost it somewhere in your house -- or you can also bring up a map to show where it is OR -- in the worst case scenario -- remotely erase the data.
Brad Rembielak
Tuesday, December 11, 2012 4:50:57 AM UTC
@Stephen Cleary - The SemaphoreSlim and async locking classes built around them are very helpful, but users have to be careful not to cause deadlocks. You mention it in a comment in your source code, but classes like AsyncLock are not re-entrant (recursive) so if you enter an async locked section and then some of that code goes on to try to enter that section again, you will deadlock. It seems obvious, but since you could execute any arbitrary code (not just in that same method) while the Semaphore is held, you might not realize you have re-entrant code. Eric Lippert's answer on StackOverflow states why something like this is not included in the framework for just that reason.

That said, I use a class very similar to AsyncLock all of the time to synchronize access to code blocks and it is quite helpful. Your site contains lots of good information on async concepts, specifically around deadlocks, so this might be something you want to point out as well.
Brian Dunnington
Wednesday, December 12, 2012 3:40:00 AM UTC
@Brian Dunnington -

You have a good point. I think I'll use re-entrant/recursive async locks as a future blog topic. :)

The MT community generally discourages re-entrant locks because non-re-entrant locks force a better design. I did look into supporting re-entrancy for AsyncLock so it could be a more direct replacement for "lock", but it's actually not possible to support async re-entrancy. :(

I took a look at the SO link you posted but couldn't see where Eric Lippert talks about re-entrancy.

If you'd like to discuss this further, feel free to start a discussion on the AsyncEx site or email me directly (from stephencleary.com). As much as I respect Scott Hanselman, I don't follow all the comments on his blog. :)
Wednesday, December 12, 2012 8:04:26 AM UTC
Why would a lock statement be necessary just because we are dealing with asyncrony? We dealt with async programming models even before the async feature and WP8. We only now have more async API's available.

If your dealing with resources only your app can access, like a file in it's isolated storage shouldn't it be enough to just set a boolean flag? We are not dealing with multithreading here, only asyncrony. The work will be syncronized to the UI thread anyway. If you set a boolean flag to prevent reentrency that should be sufficient.

You need syncronization primitives if you have multiple threads or processes accessing the same resources. Just like it was the case before we had async/await and a plethora of async apis. If you have a background agent that access your isolated storage for instance. This can happen at the same time your application runs.
Simon
Thursday, December 13, 2012 3:36:10 PM UTC
While learning about all the asynchronous locks was definetly an interesting exercise.

Couldn't you have just done this instead?

btnSave.visibility=Collapsed.
**Do all the file access stuff
btnSave.visibility=visible

The problem was that people were clicking the button too often right?
Saturday, December 15, 2012 4:19:19 AM UTC
The suggested code sample scares me! i.e. I've seen people write code like that and, all of the sudden, InvalidOperationExceptions get thrown because of nested message loops.
michael
Saturday, December 15, 2012 8:18:20 AM UTC
I was just updating my WP7 app to WP8, and I'm at the point of entering metadata, including screenshots. It got me swearing when I realized that 720p and WXGA screenshots are required. Dammit. Multiplied by 24 languages, it's a time-wasting tar-pit. Considering that screenshots need to be updated every time the UI changes -- this is a horrible mess. I'm really thinking I should just ship my app in English.... I'm in despair.
Bob
Saturday, December 15, 2012 5:41:37 PM UTC
Re: PNG nightmare, I wrote this http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/0cfa5ae0-ccc5-46c8-81e4-293f688ecc93
Monday, January 14, 2013 12:51:31 AM UTC
@Brad Rembielak

The process that you describe is different than Scott's app. It was/is available ont he Windows Phone 7 also.

@Scott,
Thanks for another great article!
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.