Monday 30 March 2015

Licensing your application

Are you willing to pay for an application before you try it? probably not, so what are your try before you buy options:

Timed Trial: start with all the features in the application and after a certain amount of time will expire and stop working, or work partially, or suddenly be riddled with ads until your user breaks down and pays or deletes it.

one thing to note is that Timed trial is not compatible with in-app purchases, that means if you have a timed trail you can't have consumable or durable products inside you application.

Feature Based Trial: start with a subset of features and require your user to pay to unlock advanced features.

In-app purchase: allow your users to make consumable purchases inside your apps; for example in games you can buy things like coins or powerups

In production we would use the CurrentApp class to handle all of our licensing information and interactivity, but for testing we use CurrentAppSimulator. Our Licencing Information is stored in an xml file at the following location:

C:\Users\Administrator\AppData\Local\Packages\49a7a3ba-c5b6-495d-be63-c1b0560ce3e7_75cr2b68sm664\LocalState\Microsoft\Windows Store\ApiData\WindowsStoreProxy.xml

now I'm using my administrator account for development, so your path will be different, now let's look inside of this xml file, but before we do it may be worth to mention that the WindowsStoreProxy.xml file is created the first time your app accesses the LicenseInformation property of the CurrentAppSimulator class.

<?xml version="1.0" encoding="utf-16" ?>
<CurrentApp>
  <ListingInformation>
    <App>
      <AppId>00000000-0000-0000-0000-000000000000</AppId>
      <LinkUri>http://apps.microsoft.com/webpdp/app/00000000-0000-0000-0000-000000000000</LinkUri>
      <CurrentMarket>en-US</CurrentMarket>
      <AgeRating>3</AgeRating>
      <MarketData xml:lang="en-us">
        <Name>AppName</Name>
        <Description>AppDescription</Description>
        <Price>1.00</Price>
        <CurrencySymbol>$</CurrencySymbol>
        <CurrencyCode>USD</CurrencyCode>
      </MarketData>
    </App>
    <Product ProductId="1" LicenseDuration="0" ProductType="Durable">
      <MarketData xml:lang="en-us">
        <Name>Product1Name</Name>
        <Price>1.00</Price>
        <CurrencySymbol>$</CurrencySymbol>
        <CurrencyCode>USD</CurrencyCode>
      </MarketData>
    </Product>
    <Product ProductId="2" LicenseDuration="0" ProductType="Consumable">
      <MarketData xml:lang="en-us">
        <Name>Product2Name</Name>
        <Price>1.00</Price>
        <CurrencySymbol>$</CurrencySymbol>
        <CurrencyCode>USD</CurrencyCode>
      </MarketData>
    </Product>
  </ListingInformation>
  <LicenseInformation>
    <App>
      <IsActive>true</IsActive>
      <IsTrial>true</IsTrial>
      <ExpirationDate>2014-06-19T09:00:00.00Z</ExpirationDate>
    </App>
    <Product ProductId="1">
      <IsActive>true</IsActive>
    </Product>
  </LicenseInformation>
  <ConsumableInformation>
    <Product ProductId="2" TransactionId="00000000-0000-0000-0000-000000000000" Status="Active" />
  </ConsumableInformation>
</CurrentApp>

lets look at the ListingInformation Node, in here it contains three children App, and two product nodes, the thing to notice is that they have two different ProductType attributes:
  • Durable: buy once keep forever
  • Consumable: buy but use up
now let's take a look at the LicensingInfromation and ConsumableInformation Nodes, these nodes contain corresponding details about the apps and purchasable products.

App: is a the node referring to our application, here it can be in trail mode that expires and can be purchased.

  • Product with type Durable: this is a product that can be purchased indefinitely an added feature.
  • Product with type consumable: a product that can be used up. 

Timed Trial

alright, lets' get started with a Timed trial app, that's an application that you download and you can use for a number of predefined days only to stop entirely or start display adds once the trial expires or perhaps only let's you utilize a subset of Features.

Let's take a look at our UI

now the xaml

<Page
    x:Class="pc.licenseExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:pc.licenseExample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock  Grid.Column="1" Text="License Exmaple"
                    Style="{ThemeResource HeaderTextBlockStyle}"
                    VerticalAlignment="Center" />
        <StackPanel Grid.Column="1" Grid.Row="1">
            <TextBox x:Name="AppData_TXT" Header="App Data:"/>

            <TextBox x:Name="ListingInfo_TXT" Header="Listing Info:"
                     Height="200" TextWrapping="Wrap"/>

            <TextBox x:Name="LicenceInfo_TXT" Header="Licence Info:"
                     Height="100" TextWrapping="Wrap"/>

            <StackPanel Orientation="Horizontal">
                <Button x:Name="GetLicenseInfo_BTN" Content="Get Info" />
                <Button x:Name="BuyLicense_BTN" Content="Buy" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Page>


let's take a look at the code behind

using System;
using System.Windows.Input;
using Windows.ApplicationModel.Store;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace pc.licenseExample
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.GetLicenseInfo_BTN.Click += GetLicenseInfo_BTN_Click;
        }

        async void GetLicenseInfo_BTN_Click(object sender, RoutedEventArgs e)
        {
            AppData_TXT.Text = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

            var listingInfo = await CurrentAppSimulator.LoadListingInformationAsync();
            var listingStr = "Age Rating: {0}\r\nCurrentMarket:{1}\r\nDescription:{2}\r\nFormattedPrice:{3}\r\nName:{4}";
            ListingInfo_TXT.Text = string.Format(listingStr,
                listingInfo.AgeRating,
                listingInfo.CurrentMarket,
                listingInfo.Description,
                listingInfo.FormattedPrice,
                listingInfo.Name);
           

            var licenseInfo = CurrentAppSimulator.LicenseInformation;
            var str = "ExpirationDate: {0}\r\nIs Trial:{1}\r\nIs Active:{2}";

            LicenceInfo_TXT.Text = String.Format(str,
                licenseInfo.ExpirationDate.ToString(),
                licenseInfo.IsTrial,
                licenseInfo.IsActive);
        }
    }
}

now what we have so far will list all of our application info when we hit the "Get Info" button and by default we can see the following


the App Data Text box gives us a link to our application in our roaming folder so that we can get to our xml file faster, I've already modified mine to have an expiry date in the past, which is why our IsActive property if false and our is Trial is true, so this tells us that the trial period is expired but the user hasn't activated the application.

so now let's write the code for buying our application, to the code behind,

public MainPage()
{
    this.InitializeComponent();
    this.GetLicenseInfo_BTN.Click += GetLicenseInfo_BTN_Click;
    this.BuyLicense_BTN.Click += BuyLicense_BTN_Click;           
}

async void BuyLicense_BTN_Click(object sender, RoutedEventArgs e)
{
    try
    {      
        await CurrentAppSimulator.RequestAppPurchaseAsync(false);
    }
    catch (Exception ex)
    {
        //handle excption
    }

}

now if we hit the buy button our isActive flag will become true, but as always we have to write the logic to deal with our licence change, luckily the LicenceInformation property has an event LicenceChanged. Let's implement that.

public MainPage()
{
    this.InitializeComponent();
    this.GetLicenseInfo_BTN.Click += GetLicenseInfo_BTN_Click;
    this.BuyLicense_BTN.Click += BuyLicense_BTN_Click;
    CurrentAppSimulator.LicenseInformation.LicenseChanged += LicenseInformation_LicenseChanged;

}

void LicenseInformation_LicenseChanged()
{
    var licenseInfo = CurrentAppSimulator.LicenseInformation;
    var str = "ExpirationDate: {0}\r\nIs Trial:{1}\r\nIs Active:{2}";

    LicenceInfo_TXT.Text = String.Format(str,
        licenseInfo.ExpirationDate.ToString(),
        licenseInfo.IsTrial,
        licenseInfo.IsActive);

}

and now our licence info will update once we simulate purchasing our application.

Durable 

Keep in mind that in-app purchases do not work with a timed-trial, so for these to work you have to open your "WindowsStoreProxy.xml" ile and change the app node to

<App>
    <IsActive>true</IsActive>
    <IsTrial>false</IsTrial>
</App>

Basically remove the expiration date node and set the istrial to false.

Now let's look at purchasing a durable, first we're going to list the durable Items so add the following datatemplate to your page's resources in the xaml

<Page.Resources>
    <DataTemplate x:Name="DurableTemplate">
        <StackPanel>
            <TextBox Header="Product Id:" Text="{Binding ProductId}"/>
            <TextBox Header="IsActive:" Text="{Binding IsActive}"/>
            <TextBox Header="Expiration Date:" Text="{Binding ExpirationDate}"/>
        </StackPanel>
    </DataTemplate>

</Page.Resources>

this will later let us view the items via ListView. Next go down to your main stack panel the one that has all our text boxes and buttons and add the following xaml

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListView x:Name="Durable_LV" Header="Durable"
            ItemTemplate="{StaticResource DurableTemplate}"/>

</Grid>

We're adding a grid with a listview is because we'll ad a second list view later for consumables, now let's add the following line to the Get Licence Info method

Durable_LV.ItemsSource = licenseInfo.ProductLicenses.Values;

Now when we run our application and get the info for our durable products.

notice we also added a buy button to the durable DataTemplate, all we did was add the following

<Button Content="Buy" Command="{Binding ElementName=MainContainer, Path=BuyDurableCommand }" CommandParameter="{Binding ProductId}" />

however this does require that we give our root page element the name "MainContainer" and that we set the pages datacontext to it's codebhind, you can see that in the following

<Page
    x:Name="MainContainer"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    x:Class="pc.licenseExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:pc.licenseExample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d">

now in the code behind we have to create an ICommand Property we can bind to, so lets add that to our class.
public sealed partial class MainPage : Page
{
    //Command to expose to UI
    public ICommand BuyDurableCommand { get; set; }

    //stuff in code behind

 }

ok, now we need to actually create a new class that implements ICommnad

public class BuyCommand : ICommand {

    Action<object> _buyCommand;

    //consturctor that takes in action to perform
    public BuyCommand(Action<object> Execute)
    {
        _buyCommand = Execute;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _buyCommand.Invoke(parameter);
    }

}

now finally we need to tie our BuyDurableCommand property to the BuyCommand class we created and we'll do that in our constructor like so.

public MainPage()
{
    this.InitializeComponent();
    this.GetLicenseInfo_BTN.Click += GetLicenseInfo_BTN_Click;
    this.BuyLicense_BTN.Click += BuyLicense_BTN_Click;
    CurrentAppSimulator.LicenseInformation.LicenseChanged += LicenseInformation_LicenseChanged;

    this.BuyDurableCommand = new BuyCommand(async id =>
    {
        try
        {
            var pr = await CurrentAppSimulator.RequestProductPurchaseAsync(id.ToString());
        }
        catch (Exception ex)
        {

        }
    });

}

now with that complete, when we run our application and purchase our durable product.