Jim O'Neil
Technology Evangelist
Join App Builder
Keep The Cash! Earn $100 for every app you publish! Let me know how I can help!
Successful apps are sticky; they make us want to come back again and again, whether it’s to check in on Foursquare, send a Tweet, or get a quick answer from ChaCha. Of all the types of apps, games can be the stickiest – Angry Birds anyone? or in my case Wordament! A great idea and implementation are obvious ingredients for success, but you also want to capitalize on opportunities to get your users re-engaged when they aren’t running your app or game.
Enter notifications, which come in two main flavors – tiles and toast – and the great thing is that your application doesn’t have to be running to receive them! A tile can update itself on a regularly occurring interval, and an external service can push information at any time to your users via the tile or by triggering a toast notification. The more engaging and dynamic your application tile is, the more likely it will beckon the user to re-launch it from the Start screen. Likewise, the more compelling and personalized a toast message is the more likely the user will switch to your app from whatever they are doing.
Must-Have Resources
Generation App
Windows Azure
Mobile Services Developer Center
Mobile Services SDK
Samples: JavaScript and HTML 5 touch game
It’s this latter scenario we’ll take a look at in this article – specifically in the context of an HTML5 game. What could be a stronger call to action to drop what you’re doing and re-play a game than just being informed that someone has knocked you out of the top position on the leaderboard!
During the course of this post, I’ll cover four primary themes, with supplementary materials available from the right sidebar:
It should come as no surprise that you’ll need some sort of centralized repository for managing game assets that are shared by all the users – like the leaderboard. The cloud, Windows Azure specifically, is a great place to host common data with little work on your part: the cloud provider, Microsoft in this case, manages all of the hardware assets and provides guaranteed uptime backed by Service Level Agreements. And with the newly launched Windows Azure Mobile Services, you can set up both storage and push notification capabilities with minimal coding on your part – freeing you up to concentrate on your game!
To take advantage and explore the possibilities, get yourself a free 90-day Windows Azure Trial Account and be sure to activate the Windows Azure Mobile Services feature as shown below. The feature is currently in preview, so it does not appear automatically when you view the various services in the management portal.
I’ve found the option is provisioned nearly immediately, so you should be able to create a new Mobile Service right away.
The key elements you need to supply to create the new service are highlighted in the two wizard screens below. Each service will have a public endpoint – mine is simplegame.azure-mobile.net. There is also a Windows Azure SQL Database supporting this service with the admin login I provided. Both the database and the services are located in the East US data center, which is currently the only data center available in this phase of the preview.
After the service has been created, take note of the Application Key, which is accessible via the menu bar at the bottom of the portal. You’ll need that and the unique service endpoint URL (*.azure-mobile.net) later.
To keep the article focused on the notification theme, versus the game itself, I opted to start with the HTML 5 JavaScript game sample on the Windows 8 Dev Center. It’s pretty simple: you simply see how many times you can touch the bouncing ball before time runs out, and it does maintain a local leaderboard which we’ll expand into the cloud.
After you’ve downloaded and installed the Mobile Services SDK, add a reference to it within the sample application.
You’ll also want to insert a reference to the Windows Runtime Component in the default.html file as follows:
7: <!-- WinJS references -->
8: <link rel="stylesheet" href="//Microsoft.WinJS.1.0/css/ui-dark.css" />
9: <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
10: <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
11: <script src="/MobileServicesJavaScriptClient/MobileServices.js"></script>
12:
13: <!-- App references -->
14: <link rel="stylesheet" href="/css/default.css" />
15: <script src="/js/assetManager.js"></script>
16: <script src="/js/movingAverage.js"></script>
The sample game implementation leverages a game JavaScript template that you could adapt for your own games as well. A key component of the template is the GameManager class, declared at the end of the default.js file. That’s a convenient singleton object to which to add a client reference to the Windows Azure Mobile Services, as shown below:
WinJS.Namespace.define("GameManager", { navigateHome: navigateHome, navigateGame: navigateGame, navigateRules: navigateRules, navigateScores: navigateScores, navigateCredits: navigateCredits, showPreferences: showPreferences, onBeforeShow: onBeforeShow, onAfterHide: onAfterHide, game: game, state: state, assetManager: assetManager, scoreHelper: scoreHelper, gameId: gameId, touchPanel: touchPanel, mobileService: new Microsoft.WindowsAzure.MobileServices.MobileServiceClient ("https://simplegame.azure-mobile.net/", “<<<---- REDACTED ---->>>") });
The premise of the notification I want to implement is that when you are knocked out of first place in the leaderboard by another player, a notification will be initiated letting you know and inciting you to reclaim your position at the top. That necessitates having at least a rudimentary leaderboard implemented, so to do that, I’ll leverage the data feature of Windows Azure Mobile Services. There will be a server component, configured in the Windows Azure management portal, and some code added to the existing sample application.
This leaderboard is quite simple and tracks only the player name, score, and level. This game doesn’t have a player registration system, so the players will be identified by whatever name was supplied on the Game Options on the Settings flyout (see right).
You might decide to incorporate your own player registration system or perhaps tap into existing identity providers like Microsoft accounts, Facebook or Twitter to authenticate player identity. Windows Azure Mobile Services can help with that too, but that’s a topic for another post!
To store the scores, I created a table within my mobile service called leaderboard. I didn’t provide a schema, because by default the schema will be created dynamically when I add data to the table; however, an unique clustered index column called id is generated for me. In production you’d turn the dynamic schema feature off (via the CONFIGURE tab of the mobile service), but for now it’s quite convenient.
Via the DATA tab of the mobile service, I created a table called leaderboard. You’ll notice there are options to control the access permissions for the various CRUD operations; this is where you might lock down access to only authenticated users or even allow access to say the leaderboard from other applications. As alluded to previously, for this scenario access to the table data is via the application key, which was used to initialize the mobile service client in the GameManager class earlier.
I also created a second table called users to contain additional information needed to implement push notifications, as you’ll see later.
With the server table in place, I just needed to hook up the client code to add a new record to the database every time a game has been completed. The sample code already has some hooks in it for the local leaderboard, so I add just a bit of code in scores.js to add a new record to the leaderboard table. The insert method here is asynchronous, and I did not supply a callback routine, so the actual leaderboard displayed in the game will continue to function as it did previously.
Here I was just interested in sending the score to the mobile service. Creating a user experience for a second ‘global’ leaderboard is beyond the scope of this article, but if you look as the functionality of the sample application (specifically in scoresPage.js), you’ll see there is some infrastructure there for multiple high score tables.
// Check if a newly achieved score should be added to the score table, ... // Return value of 0 indicates the submitted score was not good enough to ... newScore: function (score) { scoresTable = GameManager.mobileService.getTable("leaderboard"); scoresTable.insert( { player: score.player, score: score.score skill: score.skill }); var newScoreRank = 0; // TODO: Update this function to match the sort of your score table
If you were to add this code and play the game a few times, you’d see new records added into table via the BROWSE menu of the leaderboard table as shown below.
In Windows 8, push notifications are handled via the Windows Push Notification Service (WNS), which is hosted and managed by Microsoft. WNS works in conjunction with the Notification Client Platform, which is part of the Windows 8 operating system, as well as with your Windows Store application and a service that you maintain in the cloud to trigger the notifications. The process is captured by the image below, with a complete explanation of the workflow available on the Windows Dev Center.
For our gaming scenario in particular, the workflow is as follows:
The game requests a push notification channel from the Notification Client Platform on the local machine (1). The Notification Client Platform communicates with WNS (2) which returns the notification channel URI to the application (3). This URI uniquely identifies the device and the application and so will be the endpoint for future push notifications. The URI is opaque and should not be modified; furthermore, it expires after 30 days, so best practice dictates that the application renew its channel each time it runs or even as part of a background task.
The Windows Store application is responsible for maintaining the list of notification channels, which it does typically via a cloud service that triggers notifications at the appropriate times and sends them to the affected application users. In this simple HTML 5 game, the URIs are keyed by player name (4) with each player name associated with the device on which they last played the game. Remember there is currently no authentication mechanism in the game, so the last user to claim a name ‘wins.’ Obviously this would need to be rectified for a production-ready game, but it’s not a critical to understanding the push notification scenario.
When a player completes a game, his or her score is sent to the cloud service, which then checks to see if the new score is the high score. If so, the service looks up the notification channel URI for the player who was just ousted, creates a toast notification, and fires it off via WNS (5). At that point, WNS takes over and delivers the toast to the appropriate client (6) where it is surfaced to the former champion.
The steps to implement push notifications include a configuration step in which the application is registered to receive notifications followed by bit of coding in both the Windows Store application and the “Cloud Service.” In this case, the “Cloud Service” is Windows Azure Mobile Services, but in general any network accessible server that can authenticate with WNS can be used.
To set up the application to receive notifications, the Package Display Name and Publisher of the application as shown in the Package.appxmanifest are provided to Step 2 of the Windows Push Notifications & Live Connect page:
On Step 3 of the Live Connect page, three values are provided. The first, Package Name, replaces the package name in the Package.appxmanifest within Visual Studio, and the other two are provided to the mobile service (PUSH tab) in the Windows Azure Portal.
As shown in the workflow diagram, the process starts with the client application securing a notification channel. An applications request the channel, typically at startup, using the asynchronous createPushNotificationChannelForApplicationAsync method. In default.js, I added the following code to set a notificationChannel property on the GameManager when the success callback fires.
Windows.Networking.PushNotifications.PushNotificationChannelManager. createPushNotificationChannelForApplicationAsync().done( function (c) { GameManager.notificationChannel = c.uri; } );
Since the game provides an option to change player name, it doesn’t make sense to record the notification channel at the start of the application, because no one has yet played a game or registered as score. In fact, it’s possible multiple players might play on that same device, so there may not be a one-to-one correspondence of user and notification channel.
Instead, I opted to store the notification channel with the player name whenever a player completes a game. Since I established the simple rule that the user will be notified on the last device from which he or she played, the easiest way to ‘update’ the users table is issue a delete followed by an insert, right before the code that was added to update the leaderboard table.
if (GameManager.usersSeen[score.player] === undefined) { userList = GameManager.mobileService.getTable("users"); userList.where({ user: score.player }).read().done( function (results) { for (var i in results) userList.del(results[i]); userList.insert( { user: score.player, uri: GameManager.notificationChannel }); GameManager.usersSeen[score.player] = true; } ); }
The usersSeen associative array records the players who have played during the current application execution, so they are not repeatedly registered in the users table every time they complete a game.
Earlier in this post, I showed how to set up Windows Azure Mobile Services to send push notifications to the HTML 5 game. The only step left is to trigger those notifications (and craft some compelling notification text, of course).
A notification should go out to the previous top scorer whenever the newly entered score is higher. The easiest place to trigger the notification then is within the insert script of the leaderboard. Each of the CRUD operations on a data table has an associated server script, implemented via node.js, which can be used to execute custom business logic on the server.
The default insert script (right) simply executes the incoming request, but additional logic can be added, such as to detect when a new high score has been achieved and then push a notification to the dethroned player. The script I used to accomplish this appears below, followed by a line-by-line breakdown:
1: function insert(item, user, request) {
2:
3: mssql.query("select player, score, uri " +
4: "from leaderboard l, users u " +
5: "where (l.player = u.[user]) and " +
6: "(l.player != ?) and " +
7: "(l.score = (select max(score) from simplegame.leaderboard))",
8: [item.player],
9: {
10: success: function(results) {
11: if (results.length > 0 && results[0].score < item.score)
12: {
13: notify(results, item);
14: }
15: request.execute();
16: },
17: error: function(err) {
18: console.log(err);
19: request.execute();
20: }
21: }
22: );
23: }
24:
25: function notify(results, item)
26: {
27: for (var i in results)
28: {
29: push.wns.sendToastText02(results[i].uri,
30: {
31: text1: "HTML 5 Sample has a new champ!",
32: text2: "Hey, " + results[i].player + ", " + item.player +
33: " just took high score with " + item.score + " points. " +
34: "Time for revenge?!"
35: });
36: }
37: }
The experience might look a bit like that on the left for Joe, assuming that Julie just played a game on her Windows 8 tablet, and he was busy doing some Excel spreadsheet analysis at work.
What happens next? When Joe clicks on the notification, the activated event is triggered and so he’ll start up the HTML 5 game in his bid to reclaim the top position.
What if Joe happens to already be playing the game when the toast arrives and he clicks on it? Well, nothing in this case. He’s already in the application, so a click on the toast will be ignored (unless there is a launch attribute, which has not been provided in this case).
That does bring up a user experience point to consider: should a toast be displayed at all if the user is already running the application. In most cases, the application should simply absorb the new information into its display without additional fanfare. Think of Outlook for instance. When you are working with your in-box, do you really need to see toast notifications of new e-mails? They are popping up in your in-box already so the toast adds little value and can even be annoying. If you do want to ignore notifications for any reason, subscribe to the pushnotificationreceived event and set the cancel property to true; you can still introspect the notification content and act on it silently.
And that’s it! With just a little bit of coding and some great support from Windows Azure Mobile Services, we’ve put the ‘social’ into a previously solitary and isolated experience and hopefully addicted a few more users to our game!