Quickly building a trial mode for a Windows Phone application
Wow – long time no blog! Over the last few months, I took a bit of a break from blogging, but fear not – I’ve been a busy bee. Since I last blogged, a lot has changed for me. In particular, I decided to return to my home state of California. While I’m still with Microsoft (in the Bay Area), I’m no longer with the Silverlight team. I’m not done with Silverlight yet, though! I’ve continued working on various additions to my SLaB library, expanding its scope from utilities for Silverlight on the desktop to Silverlight for Windows Phone. I did most of this work in the course of building a variety of apps for Windows Phone for fun, curiosity, and utility. If you’re interested, head over to the Applications section of my website. There, you’ll see what I’ve been working on: apps for singers, barbershoppers, and everyone else!
Early on, I started porting various tools from SLaB over to Windows Phone, including many of my utility classes and my XamlSerializer. I also ported the BusyIndicator (formerly the Activity control, now in the desktop toolkit), making use of Jeff Wilcox’s PerformanceProgressBar. There are a bunch of other goodies in there too, one of which I’ll discuss in this post.
Trials and Tribulations
As I began building my first Windows Phone applications (Pitch Perfect and Tag Master), I decided early on that I wanted to include a free trial that would give people a taste of my apps while showing them “just how sweet life could be” if they were to make the purchase. Doing a little research on the topic quickly led me to the LicenseInformation.IsTrial() API. Best practices around this API, however, suggest that it shouldn’t be called too frequently, as “a typical call takes approximately 60 milliseconds or more,” and that the license state should be cached if you plan to call it frequently. Well, I honestly didn’t know how frequently I would be calling the API, and it didn’t seem like caching a Boolean value would be a costly or difficult task to accomplish, so I went ahead and abstracted it out with a utility class (which you can find in SLaB if you’re interested).
public static class PhoneUtilities { private static bool? _IsTrial; public static bool IsTrial { get { if (_IsTrial.HasValue) return _IsTrial.Value; var license = new LicenseInformation(); _IsTrial = license.IsTrial(); return _IsTrial.Value; } } }
The next problem I encountered was around testing any trial-only code in my application. There’s not a simple, built-in way to do this using the LicenseInformation API, so I went ahead and added a SimulateTrialMode static property that causes the IsTrial property to return true when it’s set. Using this API to test your trial mode is pretty straightforward. I found it most convenient to add a build configuration to my projects which I called “Release Trial” (and also a “Debug Trial” that was modeled after the Debug build configuration) that #defined TRIAL. This way, by adding the following code to my Application constructor, I could toggle between building the trial and full versions of my applications easily:
public App() { #if TRIAL PhoneUtilities.SimulateTrialMode = true; #endif // ... boiler-plate initialization code }
Look, but don’t touch!
With these APIs in place, I felt confident that I could work on producing a good user experience around my trial modes. The question, however, was what it should look like. Fundamentally, I wanted to show users what they were missing by not purchasing the app, and give them quick access should they wish to make a purchase decision. Thus, the concept I chose to develop was to obscure (with a semi-opaque overlay) the part of the UI that is not enabled during a trial and provide a link to the marketplace page for the apps in its place.
As I envisioned it, an app that looked like this when purchased:
Might look like this in trial mode:
Well, if you read my blog, you know I’m not satisfied if it’s not easy to do this in XAML, so you won’t be surprised to find out that I went about creating a control that I could use precisely for this purpose. My first instinct was to take the same approach as I originally took with the BusyIndicator control – after all, this is just a control that, based on some condition, displays an overlay and some specialized UI over its content! Instead of using a property that could be bound to a value, however, this control would simply read IsTrial to determine its behavior.
The result: a TrialBlocker control in which you can wrap your controls for instant trial functionality!
Using the control is just like using the BusyIndicator – it’s a ContentControl, and under normal circumstances (i.e. non-trial mode), it does nothing. To produce the blocked-out radio button as I did in the images above, your XAML might look like this:
<slabControls:TrialBlocker> <RadioButton GroupName="PitchRange" Content="From F to F" IsChecked="{Binding IsFromFToF, Mode=TwoWay}" /> </slabControls:TrialBlocker>
You can also replace the visuals used when the application is in trial mode by setting the TrialContent and TrialContentTemplate properties. If your TrialContent is text and you use the default TrialContentTemplate, the TrialBlocker will display the text as a hyperlink back to your application’s details in the marketplace. You can customize the content further (as I did at the bottom of the bottom-right image to produce the “Trial” link that only shows up in Trial mode) by replacing the template or using a UI element as the TrialContent. Within the content or template, a hyperlink with a Uri of “marketplace:///” will automatically link to your app’s marketplace details (using the same INavigate magic I described long ago in this post).
Thus, XAML like this:
<slabControls:TrialBlocker HorizontalAlignment="Center" TrialContentTemplate="{x:Null}"> <slabControls:TrialBlocker.TrialContent> <StackPanel Orientation="Horizontal"> <HyperlinkButton Content="Trial" Margin="-12,0" FontSize="{StaticResource PhoneFontSizeSmall}" NavigateUri="marketplace:///" /> <TextBlock Text=" " /> </StackPanel> </slabControls:TrialBlocker.TrialContent> </slabControls:TrialBlocker>
Can be used to produce a “Trial” link like this:
And that’s it! It’s a straightforward mechanism, but it does the job of producing the UI I had imagined without too much difficulty. If you think it would be useful to you, by all means, feel free to use it in your applications, too!
How about the bits?
True to form, I would never leave you without some code – you can grab it on my Downloads and Samples page. I recently uploaded SLaB v0.11 (yes, that’s zero-point-eleven – got a problem with that? ;) My releases go to eleven!), which is full of a bunch of goodies for mobile that I’ll try to blog about soon. As always, I make no promises about quality or support for the libraries – they’re just there as an example/tool for you to use if you’re so inclined! In the meantime, here’s a summary of what’s new since I last blogged:
- SLaB v0.11 (includes source and binaries I’ve accumulated by blogging)
- For the latest version, please check out SLaB on my Downloads and Samples page
- The v0.10 version of SLaB contained the following changes:
- Ported various components (e.g. XamlSerializer, etc.) to work on Windows Phone 7
- Added BusyIndicator for Windows Phone 7
- Added ContinuousButton for Windows Phone 7, allowing a bound value to be true while the button is being held down by the user
- Added the DelayCreateContentControl for Windows Phone 7, which delays creation of its content until it has been loaded
- Added the DelayLoadItemsControl for Windows Phone 7, which fires an event when scrolling nears the end of the vertical space so that more content can be loaded
- Added the DetailsLayout for Windows Phone 7, which makes creating a 2-column table of headers and content easier
- Added the MarketplaceNavigator for Windows Phone 7, which makes it easy to create HyperlinkButtons that point to marketplace content
- Added the TrialBlocker control and PhoneUtilities static methods for Windows Phone 7, which make blocking functionality for trial applications easy and testable
- Improved progress indication for network downloads
- Other minor bugfixes
- The v0.11 version of SLaB contained the following changes:
- Added the Tombstoner utilty class and a variety of helpers for Windows Phone 7, which make tombstoning of UI state simple and XAML-friendly
- Added the SequenceGrid panel for Windows Phone 7, which lays out its children in a grid (with a fixed number of columns) in the order they are added
- Other minor bugfixes
A quick note about barbershop (pun intended :))
In case you were wondering what my “Tag Master” app is all about, I’ll share with you a tidbit from my personal life. I’m a barbershopper – it’s a style of a cappella singing I grew up hearing my father perform, and fell in love with after attending my first rehearsal with a chorus in the Seattle area when I first joined Microsoft full-time. If you’ve never heard of it, do a quick search (web and Youtube) for “Barbershop quartet” or “Barbershop chorus” – I think you’ll be pleasantly surprised! It’s an amazing hobby. If you’re curious, do yourself a favor and find a local chapter!