XamlEssentials 3.3 - Phablets, Exceptions, and Stats (Oh, my!)
Hot on the heels of the last 3.2 release, XamlEssentials 3.3 is out today. This release has a couple critical features that will make it a big deal, especially if you're wanting to build for Nokia's new huge phones.
Nokia published new recommendations today on how to deal with the new screen resolutions available to Windows Phone 8 GDR3. There is some great code in their posts, and techniques on how to detect 1080p screens that are better than Microsoft's. The new properties and methods available are:
- CurrentResolution - This returns a new DisplayResolution enum with one of the 4 available resolutions for Windows Phone. This is a slightly-modified version of the code Nokia posted about here.
- IsPhablet - This tells you if the phone's screen size measures 5" or larger, which is the de-facto standard for phablets. Whether you are at 720p or 1080p, if you're on a phablet you can take advantage of the additional screen real estate differently. That's where the next method comes in. This is a slightly-modified version of the code Nokia posted here.
- AddPhabletStyle(styleDictionaryUrl) - If your phone is a phablet, this adds a separate ResourceDictionary to the end of your MergedDictionaries, which overrides any previously-defined styles. This will allow you to do things like have 3 columns of items instead of two, or extra rows of preview test for message items. It is a modified version of the technique Nokia discussed here, made generic for anyone instead of being specific to a given app.
This helper helps you determine what GDR is installed on your device, and exposes functionality that is otherwise only accessible through Reflection. Currently, there are two three properties available:
- HasGdr3 - Tells you whether or not the phone is running GDR3 or later. (Theoretically, there could be a GDR after #3, but it's unlikely. I wanted the GRD3-related helpers to still work if another release happened.)
- InstalledGdrVersion - Returns a value from the new WindowsPhone8Versions enumeration specifying which GDR is installed.
- IsBatterySaverActive - This similar to version of the helper Marco Minerva posted a few days ago, however this version doesn't use Nullable booleans. The reasoning is, if you can't access the property because you're on GDR2 or earlier, it is effectively false. Even if it could potentially be true because the mode is on, the phone can't access the value, so you aren't able to alert the user anyway (which is the primary use-case for the feature). The Nullable was just a cheap(ish) way to tell if you are on GDR3 or not. Since we can now tell you what GDR you are on, there is no need for the extra value checking that comes with using Nullables.
GDR3 also lets you optionally play a sound file with your Toast. This extension method for ShellToast can be called from any version of Windows Phone 8. It uses the PhoneVersionHelper.InstalledGdrVersion property to check for GDR3, and if possible, will play the local sound file you pass in. If you pass in an empty string, the Toast will be silent. This is a modified and streamlined version of Microsoft's official sample.
That's it for the stuff specific to GDR3, but there are a few more goodies in this release as well...
UPDATE: I pulled this one for now until I can have solid unit tests for it. I want to make sure I'm not introducing instability into your apps, and I'm just not satisfied with it yet.
A few days ago I stumbled upon this post from Nigel Sampson, which led me to an awesome post on how to handle exceptions from "async void" methods on Windows Phone 8 and Windows 8. It's a really fantastic solution, but it needed a few tweaks to get it to work without tying the code directly into a specific logging mechanism. So I replaced it with a static event you can register for, just like TaskScheduler.UnobservedTaskException. The AsyncException event will be thrown any time your async tasks from Event Handlers throw an exception. Between that, TaskScheduler.UnobservedTaskException, and Application.Current.UnhandledException, there shouldbe very few (if any) Exceptions that now slip through your cracks.
Changes to StatsHelper
We've have 3 changes to the StatsHelper that you should be aware of:
- We've updated the StatsHelper to track exceptions from the TaskScheduler, as mentioned in the previous section. This will help us count any Exceptions that happen when you don't await async calls.
- Now that we have the AsynchronizationContext, by default we will use it to replace the default SynchronizationContext automatically when you call StatsHelper.Initialize(). This allows us to track those pesky "async void" exceptions in your stats, and also makes the event available to you to provide any additional error handling. You can override this by calling StatsHelper.Initialize(handleAsyncExceptions: false)
- Finally, we've given you the option to allow our stats tracking to mark you exceptions as "handled". It's set to false by default, so that we just observe the exception and allow you to handle it. If you want us to swallow the exception so the app doesn't crash, set it to true. But a better idea would be to use AppSupport to report your exceptions without crashing your app. More details on that in a few weeks.
And the hits keep coming, folks. Hope you enjoy this release! Happy coding!