Enterprise Integration Zone is brought to you in partnership with:

Dave Isbitski is a Technology Evangelist with Microsoft focused on Windows 8. He enjoys talking about technology and has taught full-day courses on numerous Microsoft topics as well as being a presenter at VSLive!, ReMix, XAMLFest, CodeCamps and other community events. Dave can be found on Twitter at @TheDaveDev and his blog http://blogs.msdn.com/davedev. David is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

World of Warcraft API Starter Kit for Windows Phone

06.26.2013
| 3009 views |
  • submit to reddit

Overview

In my previous post I gave you an overview of my teams Starter Kits for Windows Store Apps.  I recently took the World of Warcraft Starter Kit I did for Windows, which was written in WinJS (Windows Library for JavaScript), and ported it to Windows Phone.

Since there is currently no WinJS available for Windows Phone so I chose to write a XAML/C#  native Windows Phone app and then make my network calls using the Web Browser Control.  This is the same common approach that is used in the Windows Phone HTML5 App template and other popular tools such as Intel’s XDK.

In case you missed the previous post my reasons for choosing Blizzard’s World of WarCraft APIs was to create an understandable sample app to display Realm Status (these are the game servers for World of Warcraft).  For those not in the know World of Warcraft is a very successful online game from Blizzard Entertainment® and offers an excellent open api to get game statistics.  The full API documentation can be found at http://blizzard.github.io/api-wow-docs/.

You can grab the Phone version of the Starter Kit here on Github and I have also added it to my Starter Kits section on this blog.

Currently I have implemented the WOW API into two core pieces of functionality in the Windows Phone version.

  • Realm Status (individual)
  • Realm Status (all)

Just like the Windows Store App I wanted the Windows Phone version to serve as a workable app template for helping your own apps pass certification.  Taken what I’ve learned from my own apps I’ve implemented several pieces of functionality I’ve seen developers fail certification on or get tripped up with during development.  This sample app includes workable functionality for all of the following:

    • Application Bar
    • Settings Page
    • About Page
    • Web Browser Control
    • Web Tasks
    • Calling HTML5/JS from C#
    • Small and Medium Tiles

Requirements

  • Windows 8
  • Visual Studio 2012 Express for Windows Phone or higher

Setup

Customization

Step 1. All of the Blizzard World of Warcraft API's do not require a developer key to use. However, if you plan on creating an application with heavy api usage Blizzard requests you contact them at api-support@blizzard.com to register your application.

Step 2. Currently only Realm Status is implemented. Adding additional functionality such as character or pvp info is as easy as calling the appropriate wow api (found in http://blizzard.github.io/api-wow-docs/) and then wrapping it in a function the same way realm status was done in /html/js/wowapi.js and /html/js/getRealmStatus.

Wowapi.js file contains the function call to get all of the realm statuses and then generated a bunch of div tags inside of a div in /html/index.html called divStatus.  In the Windows Store version we used WinJS data convertors to change the value of the colors in the listview columns.  For this version we are using simple CSS to color the background of each div.

 "use strict";

  

 function getRealmStatusAll() {

  

     $.getJSON("http://us.battle.net/api/wow/realm/status?jsonp=?", function (data) {

         $.each(data.realms, function (i, item) {

  

             //Add some padding between the server name cells

             var bgPadding = 'padding-top: 30px;padding-bottom: 30px;';

  

             //Check status of realm and convert background to green for online and red for offline

             var bgStyle = item.status === true ? 'background-color: green;' : 'background-color: red;';

  

             //Set up div style and show server text

             var divText = "<div style='' + bgPadding + bgStyle + "'><p>" + item.name + "<p></div><p>";

  

             //Add new div to main divStatus div

             $(divText).appendTo("#divStatus");

         });

     });

 }

  

 function onLoad() {

     //tmp until buttons included

     getRealmStatusAll();

 }

GetRealmStatus.js follows similar convention to wowapi.js but with the exception that we will now accept an argument for a single server.  This argument will actually be passed to the JavaScript function from the C# code the Web Browser Control is hosted in.

"use strict";
  
 function getRealmStatus(realm) {
      $.getJSON("http://us.battle.net/api/wow/realm/status?realm=" + realm + "&jsonp=?", function (data) {
         $.each(data.realms, function (i, item) {
  
             //Add some padding between the server name cells
             var bgPadding = 'padding-top: 30px;padding-bottom: 30px;';
  
             //Check status of realm and convert background to green for online and red for offline
             var bgStyle = item.status === true ? 'background-color: green;' : 'background-color: red;';
  
             //Set up div style and show server text
             var divText = "<div style='' + bgPadding + bgStyle + "'><p>" + item.name + "<p></div><p>";
  
             //Add new div to main divStatus div
             $(divText).appendTo("#divStatus");
         });
     }); 
  
     //alert(realm); //To Test args
 }

Step 3. Now that we have the networking calls setup (with minimal change from our WinJS Windows Store version) we need some way to display the HTML that we are generating.
This is where we will take the Web Browser Control and tell it to load the appropriate content. 

We are also using a flag here for what type of data we need to display (All or Single realms).  These flags are set in the Application scope and available from all the app’s pages.  So when a user sets a new server to track we will see those changes reflected immediately.

 // Url of Home page
         private string uriRealmsAll = "/Html/index.html";
         private string uriRealmsSingle = "/Html/realmStatus.html";
      
         // Constructor
         public MainPage()
         {
             InitializeComponent();
             InitSettings();
  
             Browser.IsScriptEnabled = true;
         }
  
         //Get server settings
         private void InitSettings() 
         {
             if (App.appSettings.Contains("realm"))
             {
                 App.userRealm = (string)App.appSettings["realm"];
             }
             else
             {
                 App.userRealm = App.defaultRealm;
                 App.appSettings.Add("realm", App.defaultRealm);
             }
         }
  
         private void Browser_Loaded(object sender, RoutedEventArgs e)
         {
             if (App.allRealms) 
             {
                 Browser.Navigate(new Uri(uriRealmsAll, UriKind.Relative));
             }
             else
              {
                 Browser.Navigate(new Uri(uriRealmsSingle, UriKind.Relative));
             }
  
         }
  
      
         private void btnAbout_Click(object sender, System.EventArgs e)
         {
             NavigationService.Navigate(new Uri("/About.xaml", UriKind.Relative));
         }
  
         private void btnSettings_Click(object sender, System.EventArgs e)
         {
             NavigationService.Navigate(new Uri("/RealmSettings.xaml", UriKind.Relative));
         }
  
         private void btnRealm_Click(object sender, System.EventArgs e)
         {
             App.allRealms = false;
             Browser.Navigate(new Uri(uriRealmsSingle, UriKind.Relative));
           }
  
         private void btnAllRealms_Click(object sender, System.EventArgs e)
         {
             App.allRealms = true;
             Browser.Navigate(new Uri(uriRealmsAll, UriKind.Relative));
         }
  
         private void Browser_LoadCompleted(object sender, NavigationEventArgs e)
         {
             if (!App.allRealms)
             {
                 Browser.IsScriptEnabled = true;
                 String[] realm = new String[1];
                 realm[0] = HttpUtility.UrlEncode(App.userRealm);
                 Browser.InvokeScript("getRealmStatus", realm[0]);
  
             }
         }

You will notice that we are passing in the server name flag to the Web Browser Control itself through the InvokeScript  method.  This allows us to generate user interaction in our native XAML based UI and then pass arguments to the JavaScript functions we load into the Web Browser Control.

Two things to point out here the first is that you must have scripting enabled on the control through the IsScriptEnabled flag and the second is that you’ll need to wait to call the JavaScript function once all the content has been loaded into the DOM.  I chose to do this through the control’s LoadCompleted Event.

Step 4.
As you add more functionality to your own app you will want to include an About and Settings page.  Both of these are set up using native XAML controls.

The About page will hand of processing to the WebBrowserTask  if a user decides to get more information.

XAML:

 <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
  
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="{StaticResource app_title}" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock Text="about" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
        <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock x:Name="txtAbout" HorizontalAlignment="Center" TextWrapping="Wrap" Text="The World of Warcraft Windows Phone 8 API Starter Kit is a completely free app for educational and entertainment purposes only. The code for this app is open source and available on Github. " VerticalAlignment="Top" Height="108" Width="446" />
            <Button x:Name="btnGithub" Content="Download Source Code" Margin="0,40" Click="btnGithub_Click"/>
            <TextBlock x:Name="txtAbout2" HorizontalAlignment="Center" TextWrapping="Wrap" Text="For more information aout my other free apps, developer starter kits, and online training courses check out my blog DaveDev.net." VerticalAlignment="Top" Height="108" Width="446" />
            <Button x:Name="btnBlog" Content="Visit DaveDev.net" Margin="0,0,0,40" Click="btnBlog_Click"/>
  
        </StackPanel>

C#:

 private void btnGithub_Click(object sender, RoutedEventArgs e)
        {
            WebBrowserTask webBrowserTask = new WebBrowserTask();
            webBrowserTask.Uri = new Uri("http://github.com/apimash", UriKind.Absolute);
            webBrowserTask.Show();
        }
  
        private void btnBlog_Click(object sender, RoutedEventArgs e)
        {
            WebBrowserTask webBrowserTask = new WebBrowserTask();
            webBrowserTask.Uri = new Uri("http://davedev.net", UriKind.Absolute);
            webBrowserTask.Show();
        }

The Settings page will store any server name that a user enters and then use that for ...

XAML:

 <Grid x:Name="LayoutRoot" Background="Transparent">
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
         </Grid.RowDefinitions>
  
         <!--TitlePanel contains the name of the application and page title-->
         <StackPanel Grid.Row="0" Margin="12,17,0,28">
             <TextBlock Text="{StaticResource app_title}" Style="{StaticResource PhoneTextNormalStyle}"/>
             <TextBlock Text="settings" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
         </StackPanel>
  
         <!--ContentPanel - place additional content here-->
         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
             <StackPanel Margin="10,58,-10,339" Orientation="Vertical">
                 <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="My Realm" Margin="10,0,0,0" FontSize="24"  />
                 <TextBox x:Name="txtRealm" HorizontalAlignment="Left" Height="72"  TextWrapping="Wrap"  Width="406"/>
  
                 <Button x:Name="btnSave" Content="Save" HorizontalAlignment="Left" Width="152" Height="91" Click="btnSave_Click"  />
             </StackPanel>
         </Grid>
     </Grid>

C#:

 public partial class RealmSettings : PhoneApplicationPage
     {
         public RealmSettings()
         {
             InitializeComponent();
             InitUserSettings();
         }
  
         private void InitUserSettings()
         {
             if (App.appSettings.Contains("realm"))
             {
                 txtRealm.Text = (string)App.appSettings["realm"];
             }
         }
  
         private void btnSave_Click(object sender, System.Windows.RoutedEventArgs e)
         {
             if (App.appSettings.Contains("realm"))
             {
                 App.appSettings["realm"] = txtRealm.Text;
             }
             else
             {
                 App.appSettings.Add("realm", txtRealm.Text);
             }
  
             var result = MessageBox.Show("Your Realm has been updated to '" + txtRealm.Text + "'.", "Changes Saved", MessageBoxButton.OK);
  
             App.allRealms = false;
             NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
         }
     }

Conclusion


Hopefully this Starter Kits will help aid you in your own Windows Phone app development. Be sure to check out the rest of my Starter Kits as well as the full APIMASH project here.

-Dave



Published at DZone with permission of David Isbitski, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)