If you follow this blog regularly, there is a strong chance that you are familiar with Bing Maps and all the greatness it brings to the web. And, with Windows 8, you can add that same greatness directly into your applications using the Bing Maps Windows Store App controls. When developing with the Bing Maps Windows Store App control, you have the option of using JavaScript or Native code (C#, VB or C++). The Bing Maps Windows Store App JavaScript control is based on the Bing Maps V7 AJAX web control. This is an excellent control with a large array of features. In addition to this, there are a ton of resources from the Bing Maps V7 control that can be used with the Bing Maps Windows Store App JavaScript control. However, as close as these two map controls may be, there are some slight differences; so don’t assume you will have 100% parity between the two.
In this blog post, we are going to look at how to create a simple application by using the Bing Maps Windows Store App JavaScript control while using the location services available in Windows 8. In addition to this, we will also take a look at testing our app on another device that doesn’t have Visual Studios installed.
Setting up your development environment
To get started developing a Bing Maps Windows Store application you will need the following installed:
- Windows 8
- Visual Studios 2012 (Get the Express version)
- Bing Maps SDK for Windows Store Apps
You will also need a Bing Maps account and key. If you intend to create a non-trial application, you should create a Basic key for your Windows Store App and read the governing TOU that defines your usage limits.
Setting up the project
To set up the project, open Visual Studios 2012 and create a new project. In the window that opens, select JavaScript -> Windows Store. Select the Blank App template, call the application BingMapsJSIntro and press OK.
A simple project will be created and contain a web page called default.html along with folders for JavaScript, CSS, and image files. The default.js file contains the logic for handing the different states of the application. Windows Store applications have three states: not running, running, and suspended. When the state changes, an event is fired, triggering the code in this file. We will not worry about handling the different states in this blog post, but it is good to take note of it as it will become useful later.
We could append the code we need for the map to this file but instead, we will keep things clean and create a separate JavaScript file for our code. To do this, right click on the js folder and select Add -> New Item. Create a new JavaScript file called bingMapsIntro.js. At this point, your Solution should look something like this:
Adding Bing Maps to the App
To get started, we will need to add a reference to the Bing Maps JavaScript library. First, right click on the References folder and press Add Reference. Select Windows -> Extensions, and then select Bing Maps for JavaScript. If you do not see this option, be sure to verify that you have installed the Bing Maps SDK for Windows 8 style apps.
Now, open the default.html file. You should see some references to all the CSS and JavaScript files already there. At this point, wherever we plan to put our Bing Maps code, we will need to add references to the Bing Maps SDK and the JavaScript file. We will also need to add a div for where we want the Bing Maps control to be loaded.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BingMapsJSIntro</title>
<!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
<!-- BingMapsJSIntro references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script>
<!-- Bing Maps references --> <script type="text/javascript" src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"></script>
<!-- Our Bing Maps JavaScript Code --> <script src="/js/bingMapsIntro.js"></script> </head> <body> <div id="myMap"></div> </body> </html> |
Next, we will need to add our logic to load the Bing Maps control. If you have used the Bing Maps V7 AJAX control before, you may already be familiar with modules. If not, modules are blocks of JavaScript code that can be used to extend the Bing Maps control by adding useful functionalities. A key benefit to using modules is that the modules fire an event when loaded. If you created your own module, you have a JavaScript file with your logic; at the end of the JavaScript file, be sure to trigger the module loaded event. So, why am I bringing this up now? Well, the Bing Maps control itself is a module which is different from what we are used to when using the AJAX control on the web. As a module, we will need to load it and create a callback function that will initialize the map. If we try to initialize the map before the module is loaded we will end up with errors. In addition, we also want to wait until the document is fully loaded before we initialize the map; otherwise, we risk trying to create the map on a div element that is not yet created which will also throw an error. Now this might sound a bit complex, but it is actually rather straight forward. Open the bingMapsIntro.js file and add the following code:
var map;
function GetMap() { var mapOptions = { credentials: "YOUR_BING_MAPS_KEY", zoom : 2 };
map = new Microsoft.Maps.Map(document.getElementById("myMap"), mapOptions); }
//Initialization logic for loading the map control (function () { function initialize() { Microsoft.Maps.loadModule('Microsoft.Maps.Map', { callback: GetMap }); }
document.addEventListener("DOMContentLoaded", initialize, false); })(); |
If you are not familiar with the last function, wrapped with brackets without a name, it is a common technique for limiting the scope of functions. By doing this, the initialize function is only made known to our event listener and therefore, not a global function. This is useful as we only need this function once.
If we run the application, we will end up with a Bing map that takes up the whole screen and looks like this.
Using Location Services
There are two ways to go about using the location services in Windows 8. The first method consists of using the Windows.Devices.Geolocation.Geolocator class and provides all the functionality needed to access the Location services on a Windows 8 device. This class has lots of features and options, but can be a bit more complex than needed.
The second method consists of using the GeoLocationProvider class, which is made available in the Bing Maps control. The benefit of using this class is that it really simplifies integration with the Location services and will also generate the accuracy circle on the map for us. We will use this approach for the sake of simplicity.
To start, we will open up the default.html file and add a checkbox to a floating div over the map to toggle the GPS (or Location services) feature. The following HTML can be added after the div for the map.
<div style="position:absolute;right:10px;top:10px;background-color:#808080;padding:5px;"> <input type="checkbox" onclick="ToggleGPS(this);"/> GPS </div> |
Next, we will need to open up the bingMapsIntro.js file and add a function called ToggleGPS. In this function, we will want to create an instance of the GeoLocationProvider class and then check to see if the checkbox has been checked or not. If it has been checked, we will want to call the getCurrentPosition method of our GeoLocationPorvider object and have a callback which adds a pushpin to the center of the returned location. The accuracy circle is drawn automatically and can be disabled through the options. If the checkbox is not checked, we will want to remove the accuracy circle and center pushpin. We will also want to cancel any outstanding requests to the GeoLocationProvider. To keep things clean, we will add an EntityCollection to the map. This is where we will add the center pushpin, versus adding the pushpin directly to the map. This will allow us to easily remove the center pushpin when we want it removed. Now we can add our ToggleGPS function and update the GetMap function in the bingMapsIntro.js file.
var map, geoLocationProvider, gpsLayer;
function GetMap() { var mapOptions = { credentials: "YOUR_BING_MAPS_KEY", zoom : 2 };
map = new Microsoft.Maps.Map(document.getElementById("myMap"), mapOptions);
gpsLayer = new Microsoft.Maps.EntityCollection(); map.entities.push(gpsLayer); }
function ToggleGPS(args) {
// Initialize the location provider if (!geoLocationProvider) { geoLocationProvider = new Microsoft.Maps.GeoLocationProvider(map); }
//Clear the GPS layer gpsLayer.clear();
if (args.checked) { // Get the user's current location geoLocationProvider.getCurrentPosition({ successCallback: function (e) { gpsLayer.push(new Microsoft.Maps.Pushpin(e.center)); } }); } else { //Remove the accuracy circle and cancel any request that might be processing geoLocationProvider.removeAccuracyCircle(); geoLocationProvider.cancelCurrentRequest(); } } |
Before we get too far ahead, we need to add the Location services to the capabilities in the package manifest; otherwise, we won’t be able to get any location information from the users device. To do this, simply double click on the package.appxmanifest file and select the Capabilities tab at the top. Under the Capabilities section, check the Location option.
At this point, we are ready to test the application. If you run the application, in the top right hand corner, you will see the check box. When clicked, the map should zoom into your location and display a pushpin on your location and a circle of accuracy.
Testing the App on a Local Machine
If you are like me, your primary development computer probably doesn’t have a touch screen. Although, maybe you have access to a touch device that has Windows 8 installed to test your app. I just happen to have an Acer Iconia Tab W500 with Windows 8. I haven’t installed anything else on it (like visual studios), so this makes for a perfect environment for testing the application. Now, how to get our newly developed app on to our other device? Well, there are a couple of ways to do this and some more complex than others. A good blog post on this can be found here. Since I created the app, and I’m deploying it onto my own machine, I’m not too concerned at this moment about security and properly signing my application. I’ll save that for when I’m ready to share it with others or deploy to the Windows Store.
So, here is an easy way to test your app. Right click on the BingMapsJSIntro project and select Store -> Create App Packages. You will be prompted with a question, “Do you want to build packages to upload to the Windows Store?” - select No and press Next. On the next screen, you can add version numbers and select the architecture to run the app on. We will leave all this as it is and press the Create button. This will generate a package for us and will provide us with a link to the folder to the package. Copy the package onto a USB drive. Next, go to your test device and plug in the USB drive. Inside the AppPackages folder, you should see a folder that has the name of our app and a version number. In that folder, you should find a PowerShell file called Add-AppDevPackage. Right click, or touch and hold so that the context menu opens up. In the context menu, click on Run with PowerShell.
Just follow the prompts that come up on the screen. When it is done, you can go to your Start screen and at the end, see your application. Now, since we haven’t added an image for the icon, our app tile is grey and has a box with an x in it. We can worry about making it look nice later.
If you click on your app it should load up. You can press the GPS and traffic checkboxes to see it work. Keep in mind that a lot more testing will be needed if you plan to deploy application to the Windows Store. For more information, take a look at this blog post.
-Ricky