26 December 2012

Handling Windows Phone 8 NFC startup events using the MVVMLight Messenger

wp_ss_20121226_0002As regular readers of this blog know, I am currently playing around with NFC on Windows Phone 8. I peeked a little in the Bluetooth app to app sample at MSDN to understand how to find a ‘peer’. A peer is defined as the same app, installed on a different phone. So basically you go around installing the app on two phones, start it on phone 1, make sure it calls PeerFinder.Start(), tap the phones together and presto - the popup as displayed in the image on the right appears. If you check ‘open app’ – or whatever it shows in the language you have selected – the app is started on the second phone as well.

You can distinguish between an app being started by itself, or with the “open app” button by overriding the OnNavigatedTo method from the app’s main startup page. If the app is all started up by itself, the NavigationEventArgs.Uri just contains the name of the main page, for instance “MainPage.xaml”. But if it is started by an NFC event, the Uri ends with the following rather funny long string:

ms_nfp_launchargs=Windows.Networking.Proximity.PeerFinder:StreamSocket

Annoyingly, the OnNavigatedTo event is only available inside the page’s code. If you want to handle this the MVVM way, you want this to be taken care of by a view model or a model, not by the page’s code behind.

I have gone the following route. First, I define a little extension method that easily helps me to determine if the app was initiated by the user or by an NFC event:

using System.Windows.Navigation;

namespace Wp7nl.Devices
{
  public static class NavigationEventArgsExtensions
  {
    public static bool IsStartedByNfcRequest(this NavigationEventArgs e)
    {
      var isStartedByNfcRequest = false;
      if (e.Uri != null)
      {
        isStartedByNfcRequest = 
          e.Uri.ToString()
          .Contains("ms_nfp_launchargs=Windows.Networking.Proximity.PeerFinder:StreamSocket");
      }
      return isStartedByNfcRequest;
    }
  }
}

And as I don’t like to pass bare events around, I make a little wrapper class to use as a message:

using System.Windows.Navigation;
using Wp7nl.Devices;

namespace PullTheRope.Logic.Messages
{
  public class NavigationMessage
  {
    public NavigationEventArgs NavigationEvent { get; set; }

    public bool IsStartedByNfcRequest
    {
      get 
      { 
        return NavigationEvent != null && NavigationEvent.IsStartedByNfcRequest();
      }
    }
  }
}

And it contains a convenient shortcut method as well. Then the only thing you have to do is indeed override the OnNavigatedTo method, like this:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  base.OnNavigatedTo(e);
  Messenger.Default.Send(new NavigationMessage {NavigationEvent = e});
}

This is the only ‘breaking’ of the purist's MVVM approach – but as the event is nowhere else available, it’s also the only way to get it done. Sometimes you have to take the pragmatic approach. Anyway, somewhere in your model or view model you define which method should be called when the message is received

Messenger.Default.Register<NavigationMessage>(this, ProcessNavigationMessage);

a method to trap it

private void ProcessNavigationMessage(NavigationMessage message)
{
  // whatever – we are back in MVVM territory
}

and I trust you can take it from there ;-) .

Be aware the events generated are generated outside the GUI thread, so if you try to data bind properties changed from the event method, you might run into cross thread access errors. Deployment.Current.Dispatcher.BeginInvoke is your friend, then.

17 December 2012

On blogging, sharing and commenting

This is not about code, but about something a fellow developer and blogger told me, which made me quite sad. It’s a kind of personal rant, so feel free to skip it if you are looking for code.

In 2007, after a frustrating search on the internet for a complete and working code sample for whatever it was, I was quite pissed off. And I decided “well if apparently people are too lazy or too much ‘look at me’ superior to post complete and working samples, I will start doing so myself”. I also could have gone to the blogs I visited posting comments like “you moron, this code is incomplete and/or wrong” or “why don’t you stop coding/blogging the cr*p you post is useless”. While technically I would have been right, I don’t think it would have helped me solve my problems. Starting blogging myself did not help me solve that problems either, but at least I had a place where I could dump my own solutions for later reference. Very handy. Apparently other people liked it too.

I was lucky enough to post a few good articles, and a few very dumb ones too, but those were met with “hey, that’s obsolete”, “hey, this is a better solution” or “I think you are missing a few steps” – with links and information. I either did take the articles down, or reworked them with the new information. I was lucky enough not to get lambasted, flamed or receive abusive comments or mails – no, my baby steps were encouraged by a few people – mostly MVPs by the way – who kind of nudged me along the rocky path of the beginning blogger.

That encouragement made me go on, becoming confident enough so that when the occasional abusive comment arrived, I was able to ignore the wording of the comment and fix the error, or challenge the commenter: “so if you are such a know-it-all, why don’t you blog about it - why do you leave me stumbling in the dark making stupid avoidable errors?”.

I recently talked to the beginning blogger I mentioned before, who was severely flamed in the beginning of his ‘career’, and he almost quit blogging of that. The wording I use in the second paragraph are more or less quotes of what he received.

This is really very counterproductive behavior. If you are someone who likes to demonstrate his/her knowledge on someone else’s blog by making demeaning remarks – realize what you are effectively doing is extinguishing enthusiasm that may have grown into the creation of a vast information resource. You are killing creativity, stomping out the sharing flame, making one of the very few willing to take time to share knowledge retreat into his/her shell, maybe never to come back again.

The very short version:

Flaming other people’s blog has never led to more examples and information. If you want more and better examples: stimulate and encourage where you can, correct if you feel you must, and try to behave like a civilized human being.

And above all, start blogging yourself. Don’t be a prick – share. Use your knowledge to improve people, not to tear them down. That’s community. That’s how it works.

Thank you.

16 December 2012

Preventing high speed socket communication on Windows Phone 8 going south when using async/await

Currently I am working on a Windows Phone 8 action game in which you can fight a kind of duel. This involves pairing the phones via NFC and then obtaining a socket trough which the phones can exchange game information. Liking to steal from examples myself (why do you think I name my blog this way, eh?) I stole code from the Bluetooth app to app sample at MSDN. Now this is a great sample but it has one kind of problem for me.

I’ll skip the pairing, the obtaining of the socket and the definition of the data reader – that’s all documented in the MSDN sample. The method to send a message to the opponent was, in condensed form:

public async void SendMessage(string message)
{
  if (dataWriter == null)
  {
    dataWriter = new DataWriter(socket.OutputStream);
  }

  dataWriter.WriteInt32(message.Length);
  await dataWriter.StoreAsync();

  dataWriter.WriteString(message);
  await dataWriter.StoreAsync();
}

while at the same time both opponenents where listening using a simple method like

public async Task GetMessage()
{
  if (dataReader == null) dataReader = new DataReader(socket.InputStream);
  await dataReader.LoadAsync(4);
  var messageLen = (uint)dataReader.ReadInt32();
  Debug.WriteLine(messageLen);

  await dataReader.LoadAsync(messageLen);
  var message = dataReader.ReadString(messageLen);
  Debug.WriteLine(message);
  return message;
}

From the debug statements in this code you can see things weren’t exactly working as planned. Now the way this is supposed to work is as follows: as the opponent sends a message using SendMessage, the other phone is receiving a message via the socket in GetMessage. The first four bytes contain an unsigned integer containing the length of the rest of the message – which is supposed to be a string.

I noticed that while things went off to a good start, sooner or later one of the two phones would stop receiving messages or both games crashed simultaneously. I got all kind of null value errors, index out of range and whatnot. When I started debugging, I found out that while the app on phone 1 said it sent a 3-character string, the receiving app on phone 2 sometimes got a huge number for the message length, that obviously wasn’t sent, it read past the end of the stream – crash.

The MSDN sample works fine, as long as it is used for the purpose it was written, i.e. sending out (chat) messages at a kind of sedate pace – not for sending a lot of events per second to keep a game in sync. The essence of a stream is that it’s a stream indeed – things have to be written and read in the right order. For what happened of course was a race condition between two or more events in a short timeframe. The first event wrote the message length, the second event as well, then possibly a third, before the first one came to writing the actual message, and whatever arrived on the other phone was a garbled jumble of bytes that did exactly reflect what happened on the sending phone, but wasn’t the orderly message length – message payload stream the other phone expected.

The way I solved it – in a ‘there-I-fixed-it’ kind of way – was to use a lock on the write code so at least stuff went in the stream in the order the other phone was expecting it:

public async void SendMessage(string message)
{
  lock (this)
  {
    if (dataWriter == null)
    {
      dataWriter = new DataWriter(socket.OutputStream);
    }

    dataWriter.WriteInt32(message.Length);
    dataWriter.StoreAsync();

    dataWriter.WriteString(message);
    dataWriter.StoreAsync();
  }
}

Note you have to remove the “await” before the StoreAsync methods as those are not allowed within a lock. This method makes sure one message – and the whole message – is written on the stream and nothing comes in between.

Update – the first version of this posting contained a small error – which has been graciously pointed out to me by a few readers (see comments section). Also, I’ve been pointed to an article by Scott Hanselman about a similar subject. I’ve tried using the AsyncLock by Stephen Toub he describes but found out that although it works very good and my game does become a bit more fluid, the lag in getting messages across is a lot higher. Net effect: while the game runs more smoothly on both phones, the game state actually gets out of sync very fast, making the game unplayable. Apparently the AsyncLock approach doesn’t work for high speed continuous message exchange, so for now I’ll stick to the approach I described above.