Monetization on Windows Phone and 8 Stores #wpdev #win8dev

Let me start by stating a few simple facts:

  1. I received first payout from Windows Phone Store after 6 months
  2. I receive regular payouts from Pubcenter – more so than store payouts
  3. I received first payout for Windows 8 store after about 15 months.

There are multiple factors that most likely contribute to what platform gives better payout. I don’t have the same apps on both platforms. Apps I created overlap but Windows Phone has many more apps than Windows 8.

Unless you have a fantastic reputation, you will need to offer Trial for you apps. The experience and API offered by SDKs are simple – it only takes into account current usage. There is no historic knowledge of what you did before. You can download a trial, use it and reinstall it and get another trial. If you don’t like this, you as a developer will have to implement checks using ANID etc.

If you don’t offer trials, you will have limited downloads.

Since Windows Phone 8 release, we know have IAP. so the Fremium model now has another option. Before you get overly excited here are some more observed behaviours.

  1. Most users will continue using an app
  2. Most people will continue using the app as long as you provide options for it to continue working while in limited functionality mode.

Let me explain: 2 of my apps have a model where I block functionality if its a free app and user navigates away from the app. In one case I stop background music player and in other I disable app specific alarms. Both of these work fine as long as the app is active and what I noticed was that instead of paying $0.99, users will continue using app with ads and restrictions.

if you think user will pay to get rid of apps, think again. sure there is money to be made from ad-revenue. however let me give you more food for thought.

  1. Most ad networks only pay per click -  biggest and baddest out there is Admob - the google monstrosity :) You can display millions of impressions yet fail to generate a penny unless your user clicks on the ad.
  2. There are a few providers which pay per impression however the ePCM is lower and if you get clicks, the ePCM rises.
  3. ePCM is measure in a chunk of 1000. for an app that attracts 0 clicks, your ePCM will be around 8 – 10p.
  4. If an app does not display say 1000 ads in a day, you wont see any revenue. like I said, works in a chunk of 1000, all or nothing.
  5. Windows Phone developers traditionally used Pubcenter as it gives a pay per view model however it only pays for a few markets – North America and Western Europe. If your user base is elsewhere you will see little.
  6. For other markets use other ad providers, user ad rotator and try different providers and see what they generate.
  7. If you want ad revenue, make games or apps for kids.
  8. If you are doing Windows 8 development, don’t bother with pubcenter :) Its a waste of time. In 1+ year I can bet that its not generated £1 in total still date even though it has received thousands of requests – there are no ads to serve.

If you think that your app will be user for substantial periods, ad supported fremium makes sense. Make sure you think about ways in which user can just navigate away yet continue using the functionality. Finally if you want user to pay up, restrict the apps.

Sorry not a very cheerful post for a Monday :) Happy coding

walking directions with using Uri Navigation #wpdev

In past, I usually opened the map control and set the location to that of the cinema. The user can then tap route option to plot the route.

Recently I decided to use HERE maps launchers to do the same.. however Glenn Versweyveld suggested that I should rather use How to request driving or walking directions for Windows Phone 8.

Using that was equally easy.. you craft a Uri and then you launch it. the system takes care of lauching drive / walk apps appropriately.

Being a good developer, I wanted to assign a name to location shown on maps so I used Destination.Name parameter with something like “Cineworld – London Enfield” being my closest cinema.

When using ms-drive, Nokia HERE Drive+ launched correctly and display destination and driving directions.

However using ms-walk, Nokia HERE Maps would start but show users current location.. nothing about destination.. totally ignored. I tweeted my frustration and Randall Arnold mentioned that he had lots of issues with ms-drive and ms-walk and that it would ignore everything after ‘-’ character.

So I stripped ‘-’ out of destination but still nothing. so I decided to strip blank space ‘ ‘. Instead of specifying the whole “Cineworld – London Enfield”, I just set Destination.Name to “Cineworld”. Bingo.. HERE Maps launches with correct destination and walking directions.

Job done.

Install Windows on a UEFI device and #wpdev sdk issues

When I got the Haswell ultrabook from Intel, it had a Windows 8 x64 build. I eventually upgraded to Windows 8.1 but I faced issues when trying to hibernate / shutting it down. This seriously affected my hobbyist dev as a I tend to leave stuff open and hibernate the device.

So to solve the problem I tried to reinstall Windows 8.1 using USB key (using Windows 7 USB / DVD tool).. however the boot loader would just ignore it and revert back to boot selection screen. I eventually reinstalled the PC using Windows 8.1 Clean and refresh option and that works as advertised. But I had some issues when installing WP8 sdk.

wp8sdk

I tried in vain to install it but it wouldn’t have anything. Eventually I figured I had to do a clean install of Windows 8.1 so scouring the next, I came across this post… the tool Rufus is almost identical to stock format tool crossed with usb dvd tool :)

rufus

That worked, the UEFI bootloader finally allowed me to install using usb key however I still have the same issue with WP SDK. Turns out some certs were out of date. I again checked for root certificate update and downloaded tool from Windows Catalogue but that didn’t do much either..

so finally I reset the system date to the day I got the device.. I remember install WP SDK then and bang it installed just fine.. silly bugger

So how did I get #GDR2 for #Lumia920

I have been debating whether to pay up for Navifirm to be able to find and install GDR2 for Lumia920. I remember Andy Wilson paying up and tweeting that he couldn’t find his devices firmware there. So I decided its not worth going down XDA-developers route, instead I could just wait a bit.

Yesterday evening, Wolfgang Ziegler, tweeted that he installed #GDR2 on his device and I said.. that’s it.. bloody hell.. time to get on with it.

So like my usual cheerful self, I quickly glanced at the post, downloaded Nokia Software for Retail 3.0.8 and back.. I have an update waiting to install.. blimey.. proceed without caution :)

Didn’t I say my usual self ?

1.3 gig download, installed in 10 mins, after configuration, of course bloody backup can’t be used as by default APN isn’t set and data connection is off.. hang on.. it was working fine when I reset the Lumia925.. quick check.. damn what.. no Amber / GDR2.. how the hell..

Oh well I suppose it was intermediate update.. plug in again and bang.. NSR says another update waiting to be installed.. for the first time I actually paid attention to the update version.. bloody thing was asking me to update the same version and forcing ROM overwrite each time..

Damn you Hermit Dave.. stupid git.. never read the instructions.. RTFM.

While trying to find Nokia Software for Retail, I remember being tempted into reading How to download Nokia Firmware with Nokia Data Package Manager.
So next step.. download and install Nokia Data Package Manager.. input correct details and search.. oops latest version is same as the one shown in NSR.

Another idea.. last year when I was hacking about trying to install 7.8 on Lumia800, I downloaded another firmware, remained a few files to match the product code and then used Nokia Care Suite. Quick check.. already had latest Nokia Care Suite – installed while I was deliberating :)
back to Wolfgang Ziegler blog, downloaded the ROM for his device :) A quick rename and tried flashing with NSR and NCS.. ooops some files are missing.. nope rename wouldn’t do…

Check on XDA-Developers said you can install other ROMs.. as long as you just pick the version, start programming, select ROM and then plug the device when prompted.. did that, it said.. product codes don’t match.. Proceed ? Hell yes.. 10 mins flashing and after a few nervous minutes.. device up and running and bang.. backup worked as APN was set correctly like on Lumia925.. wohooo looks like I have GDR2.. quick check proved that to be the case :)

Job done..

Persistent Thread like behavior with #win8dev

As you might have gathered, I
* like writing bad code
* doing things that people frown upon (like writing bad code)

Ever since I started Windows 8 Development, I miss Threads in all their glory. Sure Async Task is mostly fine but its not the same. Earlier today, Arafat asked a question about truly async logging mechanism. I suggested hacking Async Task into a thread like behaviour :) – actually it just gets you a threadpool thread :)

Task.Run provides a mechanism to queue given code on a ThreadPool for parallel execution. What happens when you refuse to return the method ? well you get the ThreadPool thread as your personal bitch :)

CancellationTokenSource CancellationSource = null;
CancellationToken TaskCancellationToken;

private async void AlwaysOnLoggingAsyncTask()
{
     while (!this.TaskCancellationToken.IsCancellationRequested)
     {
          // do something.. actually do anything
          // in the sample I was mucking around with StorageFile
          // hence the async void 

          await Task.Delay(1000); // don't kill the PC by running a tight loop.
     }
}

private async void btnStart_Click(object sender, RoutedEventArgs e)
{
     CancellationSource = new CancellationTokenSource();
     this.TaskCancellationToken = CancellationSource.Token;
     Task.Run(() => this.AlwaysOnLoggingAsyncTask(), TaskCancellationToken);
}

private void btnStop_Click(object sender, RoutedEventArgs e)
{
     CancellationSource.Cancel();
}

Here's a dummy sample logging project that incorporates this bad code :)

Update: since I was writing really bad code, I deliberately forgot to add Task.Delay. If you prefer to not write code that makes system a bit less miserable, consider adding a Task.Delay of about 1000 (1 second)

Update 2: Jarno pointed out that I am writing really really bad code - mechanism dating pre-Task era - which is correct. Old habits die hard. Well I've update the blog plus source :P to use Task Cancellation Token

Super Duper All in one VisibilityConverter for #wpdev

On the 4th of July I blogged about simple visibility converters to toggle visibility. Of course I used two converters then.. one Visibility and another inverse aka Invisibility.

I also said that some clever people might tell me that its possible to do both in a single converter. Whilst that is true, no one did so apparently no one really reads or cares :| Coding4Fun toolkit has a converter than exposes Inverted property but my idea was to be able to use the same converter by pass a parameter.

So here’s what I did

 

public class VisibilityConverter : IValueConverter
{
    public enum Mode
    {
        Default,
        Inverted,
    }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Visibility returnVisibility = Visibility.Visible;
        Mode mode = Mode.Default;
        try
        {
            if(parameter != null)
                mode = (Mode)Enum.Parse(typeof(Mode), (string)parameter, true);
        }
        catch 
        {
            mode = Mode.Default;
        }

        if (value == null)
        {
            returnVisibility = Visibility.Collapsed;
        }
        else if(value is bool)
        {
            bool bVal = (bool)value;
            if (!bVal)
                returnVisibility = Visibility.Collapsed;
        }
        else if (value is string)
        {
            string itemVal = value as String;

            if (String.IsNullOrWhiteSpace(itemVal))
                returnVisibility = Visibility.Collapsed;
        }
        else if (value is IList)
        {
            IList objectList = value as IList;
            if (objectList == null || objectList.Count == 0)
                returnVisibility = Visibility.Collapsed;    
        }

        if (mode == Mode.Inverted)
            return returnVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        else
            return returnVisibility;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

and how do I use it ? well this is how

<TextBlock Text="{Binding Review}" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>
<TextBlock Text="(rating only)" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}, ConverterParameter=Inverted}" Foreground="{StaticResource PhoneSubtleBrush}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>

I could pass Default parameter or just leave it out and it defaults to normal behaviour. If I however pass Inverted parameter to the converter, it inverts the behaviour. Bingo.

Now waiting for the next clever people to tell me that I am using parameter designed for something else :)

How to renew your Windows Store subscription using MSDN code

If you have an msdn account, you get codes for registering on both Windows Phone and Windows Store. These allow you to submit apps and generate revenue (potentially) for free since you are already playing for MSDN.

Last year while waiting for my app to be approved by App Excellence Lab, this feature was announced and having gone through 3 different AEL sessions, I found it easy to register account using MSDN provided code :)

Its almost a year since that day, I haven’t managed to generate enough revenue to pay for it but I am fortunate enough to have MSDN account and have a code at hand.

The notification email advises heading to https://commerce.microsoft.com and renewing there – alternatively you do nothing and they charge your card.

Visiting the above site, I only saw renewal options paying by card / Direct Debit or paypal.. no option to use MSDN code. I kept looking around and here’s how you do it. Copy code to clipboard and navigate to http://dev.windows.com/

Account

From dashboard, click Subscription and then click Renew button. You will get this page

code

Paste your MSDN supplied 7 character code and hit update total. After a few checks the total should be displayed as 0.00. Click Next and follow through.

Note: If your card has expired or is invalid, you will get Invalid session message and it will prompt you to start again. Click Signin and enter new card details (it needs a valid card even though you are paying 0.00) and complete the process.

Done.. you will get a confirmation email when you have completed the process. Lets hope this year brings more financial rewards to Win8dev

Background Audio #win8dev #winrt

In this post I am going to detail some of the work I have been doing on Background Audio. But before I get onto it, let me say that the last few months have been crazy / busy, not highly motivational for personal dev etc. I have done a few updates over the last few months but no new development until this month.

About 2 weeks back I started work on Porting Slydr code to WPF control and that was a breeze. Infact last night I saw something about a simple app being tested.. makes me think on whether I should beat them to it :) or not.

Now back to Background Audio. With Windows Phone, one had to create a Background Audio Player which the app and system would then communicate with. The app could kick the Background Audio Player off and then exit and the audio would keep on playing. I have talked about this before and will saying it again. WPDev 7x provided many ways of playing audio. With Windows 8 and #WinRT your options are restricted. I have gotten used to giving MediaElement more usage and credit for what it does.

<MediaElement x:Name="mePlayer" />

All you need to do is set the Source property and then call Play(). The audio starts playing. If the app gets suspended, the music stops playing. To enable background audio there are a number of things you need to do.
* Firstly set MediaElement's AudioCategory to BackgroundCapableMedia. This still doesn't activate the Background Audio as its only the first step

* Now open package.appmanifest file. Open the Declarations tab and add Background Tasks. While you are there set the Supported task types property to Audio and Control Channel. You will also need to set the Start page in App settings. Of course now that you have done this, you will have to create a Badge logo before you can save the changes to appmanifest.
appManifest

* Now back to codebehind of your page and add event handlers for MediaControl's PlayPressed, PausePressed, StopPressed and PlayPauseTogglePressed events

In my app I also support Previous Track / Next Track so I additionally added support for PreviousTrackPressed and NextTrackPressed events.

MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PausePressed += MediaControl_StopPressed;
MediaControl.StopPressed += MediaControl_StopPressed;
MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
MediaControl.NextTrackPressed += MediaControl_NextTrackPressed;
MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed;

and

void MediaControl_PreviousTrackPressed(object sender, object e)
{
    this.Previous();
}

void MediaControl_NextTrackPressed(object sender, object e)
{
    this.Next();
}

void MediaControl_PlayPauseTogglePressed(object sender, object e)
{
    if (MediaControl.IsPlaying)
        this.Stop();
    else
        this.Play();
}

void MediaControl_StopPressed(object sender, object e)
{
    this.Stop();
}

void MediaControl_PlayPressed(object sender, object e)
{
    this.Play();
}

Now when you run the app, initiate the audio playback and navigate away from the app.. Bingo. the audio is still playing.

Slides and Sample Code from Async Task talk

I have uploaded sample from from my async task talk I did last week on github.
https://github.com/hermitdave/AsyncTask

Here is the slide from the talk – Async Programming.

I started by talking about Event based async.. how framework converted sync WCF methods into event driven async methods when one adds a reference for Silverlight or Winddows Phone or Windows 8 projects. I further explained that if you had multiple dependent calls and how async task might actually help.

Next up for a very simple explanation of async task. how async task code creates a dynamic structure which is used to execute the actual code. I mentioned how async task is run on the same thread the current execution is suspended. This raised many questions.. I tried to unsatisfactorily explain the mechanism (by the looks of it). The idea was to talk through individual samples. So next I fired up App and VS and talked individual samples.

There was a hairy project moment when I was trying to show multi-threading using async task.

I think it was okay.. maybe I should have chosen an easier subject ? maybe I just need to sound more convincing next time. I am also going to have comparable async event samples side by side. There were some comments. 1st one was the same day.. very critical comment suggesting that I knew nothing (as I said async does not result in creation of new threads for execution of the said code). The chap further critisied my samples are overly simple.. and finally my projector skills (issues during the last part of event).

Oh well.. Should I continue talking on the subject ?

Implement Search Contract the easy way #win8dev

Most apps contain some sort of data that you as a developer would like exposed. That’s were the Search Contract comes into play. Say the user is on the start screen and wishes to search your app, they could just start typing and select your app from the list. If you implemented Search contract, your app will be listed in the app list and the user could just type away and hit enter to see results. That would be nice wouldn’t it ?

Lets get on with it and add search contract in a simple / easy way.
Right click on the Win8 project and select Search Contract. Name it whatever you wish and hit enter.

This does two things:

  • Adds override for OnSearchActivated in your App.xaml.cs
  • Adds required page for search and display of results.

This is what the OnSearchActivated looks like

protected async override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
{
    // TODO: Register the Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted

    // event in OnWindowCreated to speed up searches once the application is already running

    // If the Window isn't already using Frame navigation, insert our own Frame
    var previousContent = Window.Current.Content;
    var frame = previousContent as Frame;

    // If the app does not contain a top-level frame, it is possible that this 
    // is the initial launch of the app. Typically this method and OnLaunched 
    // in App.xaml.cs can call a common method.
    if (frame == null)
    {
        // Create a Frame to act as the navigation context and associate it with
        // a SuspensionManager key
        frame = new Frame();
        Cineworld.Common.SuspensionManager.RegisterFrame(frame, "AppFrame");

        if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            try
            {
                await Cineworld.Common.SuspensionManager.RestoreAsync();
            }
            catch //(Cineworld.Common.SuspensionManagerException)
            {
                //Something went wrong restoring state.
                //Assume there is no state and continue
            }
        }
    }

    frame.Navigate(typeof(SearchResults), args.QueryText);
    Window.Current.Content = frame;

    // Ensure the current window is active
    Window.Current.Activate();
}

as you can see it is passing the search query to the Search Results page while navigating.
Now lets look at the code-behind in SearchResults.xaml.
FYI, I am loading my dataset if required in the OnNavigatedTo method. This page is a simple results display page. It contains GridView / ListView to display results. Lets look at the LoadState method

protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    var queryText = navigationParameter as String;

    List<SearchResult> matches = new List<SearchResult>();

    foreach (var f in App.Films.Values)
    {
        IEnumerable<CastInfo> casts = from cast in f.FilmCast
                                        where cast.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                        select cast;

        foreach (var c in casts)
        {
            //searchCinemas.Add(c.Name, c);
            matches.Add(new SearchResult() { Name = c.Name, Subtitle = String.Format("{0} in {1}", c.Character, f.Title), SearchObject = f, Image = c.ProfilePath });
        }
    }

    IEnumerable<FilmInfo> films = from film in App.Films.Values
                                    where film.Title.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                    select film;

    searchFilms.Clear();
    searchCinemas.Clear();

    foreach (var f in films)
    {
        searchFilms.Add(f.Title, f);
        matches.Add(new SearchResult() { Name = f.Title, Image = f.PosterUrl, SearchObject = f });
    }

    IEnumerable<CinemaInfo> cinemas = from cinema in App.Cinemas.Values
                                        where cinema.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                        select cinema;

    foreach (var c in cinemas)
    {
        searchCinemas.Add(c.Name, c);
        matches.Add(new SearchResult() { Name = c.Name, SearchObject = c, Image = new Uri("ms-appx:///Assets/Background.png") });
    }
            
    // TODO: Application-specific searching logic.  The search process is responsible for
    //       creating a list of user-selectable result categories:
    //
    //       filterList.Add(new Filter("<filter name>", <result count>));
    //
    //       Only the first filter, typically "All", should pass true as a third argument in
    //       order to start in an active state.  Results for the active filter are provided
    //       in Filter_SelectionChanged below.

    // Communicate results through the view model
    this.DefaultViewModel["QueryText"] = '\u201c' + queryText + '\u201d';

    bAllowNav = false;

    this.DefaultViewModel["Results"] = matches;

    bAllowNav = true;

    var filterList = new List<Filter>();
    filterList.Add(new Filter("All", 0, true));

    //this.DefaultViewModel["Filters"] = filterList;
    //this.DefaultViewModel["ShowFilters"] = filterList.Count > 1;
}

I added code to search my dataset and to add results to DefaultViewModel. I don't use MVVM but the default code implemented basic binding etc and I thought I'd leave it at that. I accumulate the results and save them and let bindings do the rest. Let me show you how it looks
Say I got to start screen, type I ben and select my app, this is what I get.

Now you have a nice list of matched entries. Now suppose I wanted to let users click on a matched entry and to navigate them to details page ? I implemented GridView ItemClick event (SelectionChanged doesn't work for some reason)

private void resultsGridView_ItemClick(object sender, ItemClickEventArgs e)
{
    if (e.ClickedItem != null && bAllowNav)
    {
        SearchResult res = (SearchResult)e.ClickedItem;
        if (res.SearchObject is FilmInfo)
        {
            FilmDetails.SelectedFilm = (res.SearchObject as FilmInfo);
            this.Frame.Navigate(typeof(FilmDetails));
        }
        else if (res.SearchObject is CinemaInfo)
        {
            CinemaDetails.SelectedCinema = (res.SearchObject as CinemaInfo);
            this.Frame.Navigate(typeof(CinemaDetails));
        }
    }
}

Hope this post is helpful to others looking to implement the search contract. Happy coding!