(Download Source Code)
Windows Phone 7 provides the LicenseInformation class that includes the IsTrial() method. IsTrial() allows you to check, at runtime, if the running application has been installed from the Marketplace as a trial application, or if the user has purchased the application. Developers are able to use IsTrial() to change the behavior of their application based on whether or not the user is running a trial version or a paid for version. Unfortunately for WP7 devs, there is no easy way to control the IsTrial() results when developing and debugging their applications. IsTrial() will always return False when developing an application. Even more disappointing, LicenseInformation is a sealed class and there is no ILicenseInfo interface that you could use to mock out your own implementation while developing.
In addition, each developer is left to his or her own devices to come up with a system for controlling how their trial software behaves. Simple things like turning of features in the trial version is pretty straightforward, but if you want to have a more complex behavior, things get trickier. What if you want someone to be able to use your application for 30 days before you disable features? How about 10 uses of the application before they need to buy the full version? You are on your own.
TrialManager is a simple piece of code that you can add to any WP7 project to help manage the behavior of your trial apps. TrialManager will also make it easier to simulate you application running in Trial mode when creating your apps. You can get the source to TrialManager here. Feel free to use it, modify, etc. The only licensing restriction is that I ask you send me an email letting me know you are using the code in some form or fashion.
Setting Up TrialManager for Usage Tracking
To get start with TrialManager, just at the SlickThought.Phone.dll to your Windows Phone project. After that, the first thing you need to do is modify your App.xaml file to instantiate TrialManager each time your application runs. The nice thing about TrialManager is that all of its behavior is configured using App.xaml. Here are the changes you would need to make in your app to get started…
Next, we modify the Application.ApplicationLifetimeObjects element as shown below:
<trial:TrialManager RunAsTrial="True" Expired="TrialManager_Expired" >
This will cause our WP7 application to instantiate the TrialManager every time the application loads. It doesn’t matter if it is the first time the app launches of if we are pulling the app off the back stack, we will get a brand new TrialManager object. Taking a look at the markup, there are a few things to note. First, we can have the TrialManager to simulate that the application we are developing is running in trial mode by setting the RunAsTrial property to True. TrialManager has its own IsTrial() method, just like the LicenseInformation class. Normally, TrialManager.IsTrial() will create its own LicenseInformation object and return that object’s IsTrial() result. When we set RunAsTrial to True, however, TrialManager will always return True for a call to IsTrial(). The code for TrialManager.IsTrial() is shown below:
if (_license == null)
_license = new LicenseInformation();
Second, TrialManager has an Expired event that is fired when the ExpirationPolicy object fires its own Expired event. In the example above, we are wiring the Expired event to an event handler named TrialManager_Expired. In the sample application, a MessageBox is shown when the application expires. In your own application, you would probably do something like using the MarketPlaceLauncher to redirect the customer to your applications details page in order to buy a full version.
The TrialManager’s behavior is controlled by the object assigned to the ApplicationProperty property. This object must be derived from the ExpirationPolicy base class. TrialManager comes with two implementations for you to use: UsageExpirationPolicy and TimeExpirationPolicy. The UsageExpirationPolicy is the easiest to set up. In our example, we are setting up a MaxUsage to 5. What MaxUsage means is entirely up to you. You control how to increment the UsageCount property. You could do it each time the application starts or when a particular feature is used. It is as easy as the following:
(TrialManager.Current.ApplicationPolicy as UsageExpirationPolicy).UsageCount++;
When UsageCount exceeds MaxCount, the UsageExpirationPolicy will fire its Expired events, which in turn causes TrialManager to fire its Expired event.
Setting Up and Using Trial Expiration
The other ExpirationPolicy derived class is the TimeExpirationPolicy. An example of configuring TrialManager to use the TimeExpirationPolicy is shown below:
<trial:TrialManager RunAsTrial="True" Expired="TrialManager_Expired" TimerInterval="00:05:00" >
<trial:TimeExpirationPolicy TrialDuration="01:00:00" Mode="Lifetime" />
In this case, we set up a TimeExpirationPolicy object in the XAML. The most important property is the TrialDuration property. Here, you set the TimeSpan that you want to make the application available before expiring. The Mode property is optional. By default, the Mode property is set to Lifetime. Lifetime durations mean that the cumulative ElapsedTime for the application is tracked each time the application is used. If the user runs an application for five minutes the first time, and fifteen minutes the second time, TrialManager will record this as twenty minutes of total usage and compare that value to the TrialDuration. You can also set the Mode property to Session, which specifies that the ElapsedTime is reset to zero each time the application is launched. When using the TimeExpirationPolicy, the TrialManager creates a DispatcherTimer and uses this to track the applications time usage. By default, the DispatcherTimer.Interval property is set to one minute. You can override Tick interval by setting the TimerInterval Property on the TrialManager. In the example above, we are setting the Tick of the DispatcherTimer to five minutes.
Other Things About TriaManager
A couple of other notes about using TrialManager:
- TrialManager has a DoNotPersist property. By default, TrialManager will persist the state of the ExpirationPolicy to IsolatedStorage each time the application is exited (either via Deactivate or Closed). This means the only way to get rid of persisted state information is to recycle the emulator. Setting the DoNotPersist property to True will prevent the TrialManager from persisting state when the application is exited making debugging in certain situation easier.
- The ExpirationPolicy base class has an Expired event. This means you can hook up the Expired event at either the TrialManager or at the ExpirationPolicy level. TrialManager actually hooks to the ExecutionPolicy’s Expired event and just fires its own Expired event when the ExpirationPolicy fires its event. In the future, I see TrialManager having different ExpirationPolicy objects to control different features. There will be an application level ExipirationPolicy, which will always cause the main TrialManager Expired event to fire. Just an FYI…