Thursday, January 27, 2011

Mobile Panel at #DDD9

Due to a late change to the DDD9 session schedule there will now be a Mobile Panel session at the end of the day.

The panel will be discussing:

"mobile devices, mobile web and anything in between"

I'll be on the panel. If you're going to be at the conference do come along to what will hopefully be a very interesting discussion and, apparently, the first ever panel session at DDD.

Saturday, January 22, 2011

Gotchas when integrating with the Music and Video Hub #WP7Dev

If you are making a Windows Phone 7 app which can, or needs to, integrate with the Msuic & Video hub, Microsoft have provided some instructions on doing this:

http://windowsteamblog.com/windows_phone/b/wpdev/archive/2010/11/04/integrating-your-app-into-the-music-videos-hub.aspx
and
http://msdn.microsoft.com/en-us/library/ff769558(VS.92).aspx

There are however a few points which aren't currently (well) documented (yet):

MediaHistoryItem.Source


To integrate with the M + V Hub requires use of the MediaHistoryItem.

The MediaHistoryItem has a Source property which the Intellisense in Visual Studio tells us not to use:


If we don't set it though we get an error. Yes, even though we're told not to use it.
Infact, we have to set it to an empty string.

If we dig into the remarks for the property in MSDN we do find a note about this:
"Although this property is unsupported, you must set its value to "", meaning a blank string, whenever you instantiate a new MediaHistoryItem."

MediaHistoryItem.Title


Another property of the MediaHistoryItem is Title. This is a required property.

At this point it should be noted that there are 3 occasions to use the MediaHistoryItem: When adding a new item; When updating the Now Playing item; and when updating the recently played list.
For all of these scenarios you must set the Title to something, but it's only actually used when setting the "NowPlaying" item.


MediaHistoryItem.ImageStream


When specifying the stream of the image to use for the tile in the M + V hub, there is documentation about the Application Certification Requirements with regards to the images that are used but somewhat unhelpfully it's easy to miss that the stream must be smaller than the undocumented MaxImageSize.
This size is just 16KB.

System.ArgumentException: image stream size bigger than maximum allowed 16384

This may seem quite large for a an image just 358x358 or 173x173 pixels in size. (Your image will be resized and/or cropped if not the specified dimensions - but you may not get through Marketplace certification if you rely on this.)
You may hit an issue if you are using a complex image for the tile (which you have if using album artwork or a packshot image) and wish to maintain a high quality image.
If you have this issue you may wany to consider using a solider colour border around the image to allow you to maintain a higher image quality (meaning lower jpeg compression is needed).

MediaPlayerLauncher & WMDRM


MediaPlayerLauncher makes it easy to play WMV files from IsolatedStorage:

    var mpl = new MediaPlayerLauncher
                    {
                        Controls = MediaPlaybackControls.All,
                        Location = MediaLocationType.Data,
                        Media = new Uri("filename.wmv", UriKind.Relative)
                    };

    mpl.Show();

But if you're WMV file uses WMDRM, rather than PlayReady DRM then things get tricky.

Unfortunately, Silverlight doesn't support WMDRM, only PlayReady DRM.
Fortunately, Silverlight provides a way to override the use of WMDRM and use a PlayReady license server instead.
Unfortunatley, MediaPlayerLauncher doesn't support this.
Fortunately, one of the features of Silverlight 4 which was included in Silverlight on WP7 was the ability to support persistent PlayReady DRM licenses.

So what can we do?

Assuming we're able to issue persistent PlayReady licenses (a separate issue I won't discuss now) we can combine the use of MediaPlayerLauncher with the use of MediaElement.

We can use the MediaElement (which includes a LicenseAcquirer and in turn the LicenseServerUriOverride property) to get a PlayReady license.



    forLicenseAcquisition.LicenseAcquirer.LicenseServerUriOverride =
        new Uri(AppResources._RightManagerAddress + urlGetParams, UriKind.Absolute);

    using (var store = IsolatedStorageFile.GetUserStoreForApplication())
    {
        var movieFileStream = store.OpenFile("filename.wmv", FileMode.Open, FileAccess.Read);
        forLicenseAcquisition.SetSource(movieFileStream);

        forLicenseAcquisition.Play();
    }

Once the license has been received the MediaElement will start to play. We can then handle the event raised when the MediaElement starts to play.
In that handler we stop the playing via the MediaElement and then start it in the MediaPlayerLauncher.

    private void forLicenseAcquisition_MediaOpened(object sender, RoutedEventArgs e)
    {
        forLicenseAcquisition.Stop();

        // record that license acquired

        var mediaHistoryItem = new MediaHistoryItem();
        mediaHistoryItem.Title = "My Movie";
        mediaHistoryItem.Source = string.Empty; // Must be set but unused

        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            mediaHistoryItem.ImageStream = store.OpenFile("tile_image.jpg", FileMode.Open, FileAccess.Read);
        }

        mediaHistoryItem.PlayerContext.Add("Movie_Title", "My Movie");

        MediaHistory.Instance.NowPlaying = mediaHistoryItem;

        var mpl = new MediaPlayerLauncher
        {
            Controls = MediaPlaybackControls.All,
            Location = MediaLocationType.Data,
            Media = new Uri("filename.wmv", UriKind.Relative)
        };

        mpl.Show();
    }

This only works with a persistent license though. I don't see this being too much of an issue though as if the content is being loaded onto the device (phone) then the owner of the phone should (I would argue) be allowed to play the content at any time, even if they're not able to connect to the PlayReady server. (They will still need that connection the first time though.)

If doing this, it's also wise to handle the MediaElement Failed event in case there is a problem getting the license.
It's also wise to keep track of which content a license has been acquired for. This means that you can skip the need to use a MediaElement on future attempts to play the content. This means that content can be loaded and therefore start playing faster on subsequent times.

I hope someone will find the above useful. ;)

Thursday, January 20, 2011

What makes a great application?

Really thought this was worth noting from the keynote of #uktechdays online conference today:

Q. What makes a great application?

A. A combination of Core Architecture and User Experience.

Core Architecture is made up of:
  • Functionality
  • Reliability
  • Scalability
  • Security
  • Performance

The User Experience involves:
  • Delighting the user
  • Being easy to use
  • Being powerful
  • Being focused
  • Being flexible

Wednesday, January 19, 2011

WP7Dev at VBUG Reading (Bracknell)

Last night I went over to VBUG in Reading to talk about getting started with developing for Windows Phone 7. I thoroughly enjoyed myself and everyone said the talk was interesting and useful.

As ever there were lots of questions, which I consider a good thing as it means people are getting the information they want. (Assuming that I could answer them all - which I managed yesterday!)

There were a few requests for information which I said I'd help point people towards. As such, here are:

My slides: http://www.slideshare.net/mrlacey/introducing-windows-phone-7-development

(most of) My demo code: http://cid-cc22250598bf7f04.office.live.com/self.aspx/Public/WP7-UserGroups.zip

A comparison of currently available phones: http://wmpoweruser.com/windows-phone-7-device-comparison-chart/

The new Push Notification Service helpers: http://create.msdn.com/en-us/education/catalog/article/pnhelp-wp7

MSDN docs: http://msdn.microsoft.com/en-us/library/ff402535(v=vs.92).aspx

A great place to ask any questions: http://stackoverflow.com/questions/tagged/windows-phone-7

If anyone is interested I'll also be giving a very similar talk at the Canary Wharf Dot Net User Group on Feb 2nd. Details at: http://www.meetup.com/cwdnug/calendar/15949204/

Friday, January 07, 2011

16 ways to make your WP7 game better #wp7dev

One of the great things about Windows Phone 7 is all the games available.

Over the last few weeks, I've definitley spent more time than I probably should playing just a few of them.


Not being one to miss an opportunity to find ways to improve the apps (and games) I'm working on and may build in the future, I've been looking for lessons I can learn from other people's games. Some of these lessons are based on identifying things which some games do well, some on things some games do badly and some on my own ideas and observations.

In the hope that these lessons can also help you improve the apps you create, here's the list of points I've drawn up. This is in no way an absolute or complete list but that shouldn't invalidate it's value. (While specifically relating to games, many of these points could be applied to any application.)

In no particular order:

  1. Lots of short levels are preferable to a few big ones.

    This is especially true if the game doesn't support tombstoning (or any form of saving and resuming later). It also better suits a mobile environment where users will typically play for shorter periods of time compared to other platforms.

  2. Get tombstoning right, so I don't lose my place in a game.

    Unfortunately there are lots of games that don't support saving games part way through. Because of the nature of the phone I can't guarantee not being interrupted and so if I can't save my game at any point (whether the interruption was my choice or not) can be very frustrating.

  3. Keep multiple copies of saved state so that even if there's a problem you can revert back to the slightly older copy as its preferable to go back a bit in a game than to lose everything.

    Unfortunately, (presumably at least in part) due to the large amount of data a game needs to save to resume later, quite a few games I've played have crashed when trying to resume a previously saved game. The framework will automatically close the game if it takes too long to perform certain tasks (including resuming a game). In all of these cases the only solution was to start the game again, thereby losing all progress. If practical I'd like to see a game take periodic snapshots of game state (some games do do this. e.g. at certain points in a level anyway) and then if when attempting to resume it's not possible to successfully restore a game based on a specific copy of the saved state

  4. Don't screw up the back button!!!

    The rule of the back button (for >95% of apps) is that (with the exception of a possible dialog to confirm closing) repeatedly pressing the hardware back button will close the application. Unfortunatley there are a few games which break this rule. This can be very frustrating!

  5. Evenly balance all achievements

    Don't just achievements that will mostly be achieved in the first few minutes of play and then a couple for having played for a VERY long time or (for example) 1000 Games or earing a million points. Achievements should be achieved as the user progresses through a game, not all at the start.

  6. Show progress towards achievements

    If you have achievements based on the number of times something is done or the total time spent playing a game then indicate the progress being made towards those numbers/lengths of time

  7. Don't use technical, meaningless terms in unnecessary prompts.

    Seriously, just don't. To a non-technical user you will just confuse and potentially frustrate. "Why do you keep asking me this question I don't understand. Cancel."

  8. Be smart about touch targets

    If a game has lots of touchable items close together and I try and click on something I can't but its right next to something I can, assume I meant to click on the thing I can click on. An example of this would be a game which has certain spaces where you can place "pieces" and the user touches the already populated space next to an empty space. Yes this can mean that the touchable area for items will change based on it's neighbours (which may be complicated to program) but the alternative is to frustrate users. Your choice.

  9. Don't save all details on a single config file

    Because if the stored game state fails to save and all details lost I don't want that to lose my entire history. e.g. Total points across all games or number of games played. Use multiple files and/or IsolatedStorageSettings as appropriate.

  10. If your about screen contains URLs and email addresses make them clickable/actionable.

    Do you seriously expect me to type in your url or email address when you're to lazy to wire up a touch event to launch a task? And if I have to contact you because of a problem I'll be even more frustrated because of this. Just saying.

  11. Let me exit the app at any point, not just at the end of a level/go.

    Specifically in response to navigating via internal menus or the hardware back button. (Yes I know it's possible to exit via the start or search buttons.) This is a variation on the above point about breaking the back button but I can't see any reason why I shouldn't be able to exit at any point in the game, even if I'm happy to lose my progress/state within the game.

  12. If I'm listening to the radio when I start your game don't ask me about "custom music"

    This is a specific variation of the above point about unnecessary prompts. Why is the music "custom"? What does "custom music" even mean. The point hear is to word your dialogs carefully to match user terminology. I suspect they meant to refer to "currently playing music".

  13. If you prompt me to confirm closing the game don't add another screen after that where I have to select quit again.

    I seriously don't understand why anyone would even think this was acceptable. As a user I find this frustrating and confusing. What happened? Did the game actually close? Why do I have to press "Quit" 4 times to close this game?

  14. Its better to show loading progress in lots of small steps than a few big ones

    Responsiveness is even more important on mobile devices. Having a loading status information message or progress bar length update more frequently can give extra reassurance to the user that they are progressing towards being able to play thier game sooner. In some instances, a more frequently updated progress bar can also give the perception that the total load time was less than an infrequently updated one.

  15. Having an on screen back button can be useful for navigating between pages.

    Don't rely on the hardware back button if your game only plays in a landscape orientation. Most landscape games have an onscreen way of navigating back so by not having one you add an moment of confusion to the user as they try and work out what they're supposed to do to navigate.

  16. If you have a lot of instructions / help (which is probably good) don't just have it all in one place (as a single long list).

    Provide relevant info, in pieces, as the user advances through the game. It's much easier to take in this way and a user is more likely to remember it when they need it. This all serves to help the user learn the game as they need to and become less frustrated by having to try and work out what they need to do. The challenge should be in playing the game, not how to play the game.

Do you like my new layout?

I thought it was time for a change. Well, I've had this blog since 2006!

In that time the layout has changed very little. (Possibly only once but I can't say for sure.)

In case you care (have forgotten), here's how it looked before:


As ever, any comments, feedback, suggestions, etc. are very welcome.

Wednesday, January 05, 2011

Speculation about what's coming next to Windows Phone 7

We know that cut & paste will be coming to Windows Phone 7 in an update later this month.

We've also heard that there will be another update in February. At the moment we don't know what it will include though.

I don't have any inside knowledge about what the February update will include. Nor do I know what or if anything else will be included in the January update.

I do know what I'd like to see though*:
  • More core functionality exposed in the managed SDKs
  • An update to Internet Explorer
  • Release of specific details about support for smaller screens
  • Details about small screen device availability
  • The ability to get the name of a contact as well as their email address or phone number when using the appropriate task
  • A way to integrate with the built in maps app

Realistically though, I'd be happy if any of the above were added.
If I could pick just one I'd take details about small screen device support.

* Obviously I'd like to see more in the long term but these will do for now.