Cross Platform Development with Bing Maps and PhoneGap

Bing Maps provides a variety of APIs and controls. One of which is the Bing Maps AJAX Control that was originally designed to provide interactive maps for the web but meanwhile also powers the WinJS control in the Bing Maps SDK for Windows Store apps. The Bing Maps AJAX control has a slim core to speed up the initial load of a website, is optimized for performance using HTML5 technologies and implements a modular concept that allows the loading of additional modules on-demand. Official modules include the search for locations and business listings, driving directions, traffic overlays, venue maps and more. Our friends in the developer community have picked up this modular concept and developed further modules which extend the AJAX control. An Interactive SDK makes it very simple to become familiar with the control and implement your first maps within minutes.

Another big point for the AJAX control is, that it cannot only be used for websites but also in the context of PhoneGap / Apache Cordova. PhoneGap enables JavaScript developers to build native applications for a number of platforms including Android, iOS and Windows Phone. Getting Started Guides help you over the first hurdles for all supported platforms. No matter if you are used to Visual Studio, Blend, Eclipse or Xcode, if you are familiar with HTML, JavaScript and CSS, you can get your first mobile applications of the ground very quickly.

image

Once you have your app running on one platform it is a walk in the park to move it over to other platform. You don’t need to be an expert on Objective C, Java and .NET to support Windows Phone, Android and iOS. You can simply write your application in HTML, JavaScript and CSS and let PhoneGap / Apache Cordova handle the rest.

Getting Started

Let’s put that concept to a test. We start with the projects from the Getting Started Guides for PhoneGap as well as a simple web application that features Bing Maps and allows us to search for locations and business listings. Below you find the HTML-document.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" type="text/css" href="css/index.css" />
    <script 
       type="text/javascript" 
       src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0">
    </script>        
    <script type="text/javascript" src="js/index.js"></script>
    <title>Bing Maps</title>
  </head>
  <body>
  <div id='divSearch' 
       style="position:absolute; top:5px; left:0px; right:0px; height:50px; 
       background-color:White; ">
    <input id="txtSearch" type="text" class="searchBox" />
    <img id="btnSearch" src="./img/search.png" alt="" 
         style="position:absolute; top:0px; right:0px; 
         cursor:pointer" onclick="LoadSearchModule()" />
  </div>

  <div id="divMap" style="width:100%; height:92%; 
       position:absolute; left:0px; top:55px;"></div>
  </body>
</html>

And here is the JavaScript-file that loads the map, applies some themes for controls and pushpins, handles the search for business listings and displays pushpins as well as info-boxes when you click on such a pushpin. You can find all the pieces for this sample in the above mentioned interactive SDK.

window.onload = GetMap;

var map = null;
var searchManager = null;
var currInfobox = null;

function GetMap(){
    Microsoft.Maps.loadModule('Microsoft.Maps.Themes.BingTheme', { callback: function() 
        {
            map = new Microsoft.Maps.Map(document.getElementById('divMap'), 
            { 
                credentials: "Your Bing Maps Key",
                mapTypeId: Microsoft.Maps.MapTypeId.road,
                enableClickableLogo: false,
                enableSearchLogo: false,
                center: new Microsoft.Maps.Location(47.603561, -122.329437),
                zoom: 10,
                theme: new Microsoft.Maps.Themes.BingTheme()
            }); 
        }
     });
}

function createSearchManager() {
    map.addComponent('searchManager', new Microsoft.Maps.Search.SearchManager(map));
    searchManager = map.getComponent('searchManager');
}

function LoadSearchModule() {
    Microsoft.Maps.loadModule('Microsoft.Maps.Search', { callback: searchRequest })
}

function searchRequest() {
    createSearchManager();
    var query = document.getElementById('txtSearch').value;
    var request =
        {
            query: query,
            count: 20,
            startIndex: 0,
            bounds: map.getBounds(),
            callback: search_onSearchSuccess,
            errorCallback: search_onSearchFailure
        };
    searchManager.search(request);
}

function search_onSearchSuccess(result, userData) {
    map.entities.clear();
    var searchResults = result && result.searchResults;
    if (searchResults) {
        for (var i = 0; i < searchResults.length; i++) {
            search_createMapPin(searchResults[i]);
        }
        if (result.searchRegion && result.searchRegion.mapBounds) {
            map.setView({ bounds: result.searchRegion.mapBounds.locationRect });
        }
        else {
            alert('No results');
        }
    }
}

function search_createMapPin(result) {
    if (result) {
        var pin = new Microsoft.Maps.Pushpin(result.location, null);
        Microsoft.Maps.Events.addHandler(pin, 'click', function () { search_showInfoBox(result) });
        map.entities.push(pin);
    }
}

function search_showInfoBox(result) {
    if (currInfobox) {
        currInfobox.setOptions({ visible: true });
        map.entities.remove(currInfobox);
    }
    currInfobox = new Microsoft.Maps.Infobox(
        result.location,
        {
            title: result.name,
            description: [result.address, result.city, result.state, 
              result.country, result.phone].join(' '),
            showPointer: true,
            titleAction: null,
            titleClickHandler: null
        });
    currInfobox.setOptions({ visible: true });
    map.entities.push(currInfobox);
}

function search_onSearchFailure(result, userData) {
    alert('Search failed');
}

Building the first Mobile App

Let’s create a Windows Phone application from this website. If you followed the Getting Started Guides for PhoneGap you have a project structure with a folder “www” under which the HTML-document, the styles, images and JavaScripts are organized.

image

In the head of index.html we need to introduce 2 additional meta-tags to prevent the browser from capturing pinch-to-zoom events and another one that disables format-detection for phone-numbers. Next we need to reference the main PhoneGap / Apache Cordova script.

<head><meta name="format-detection" content="telephone=no" />
  <meta name="viewport" 
        content="user-scalable=no, initial-scale=1, 
                 maximum-scale=1, minimum-scale=1, 
                 width=device-width, height=device-height, 
                 target-densitydpi=device-dpi" /><script type="text/javascript" src="cordova.js"></script></head>

We also need to verify if the path to the images and style sheets is correct.

In the JavaScript we only need to replace a function that fires in the web-browser when the window is loaded with one that PhoneGap has implemented to detect when the app is launched ready to interpret the JavaScript code. We simply search for…

window.onload = GetMap;

…and replace it with

document.addEventListener('deviceready', GetMap, false);

And that is really already it. Run your code in the device emulator or a physical device to check it out.

Porting the app to other platforms

There can certainly be a bit of effort in applying typical styles for the different platforms but if we just look at a simple user interface and the application logic itself the porting from Windows Phone to iOS or Android is literally just copy and paste. PhoneGap will take care of the device-specific impplementations. We can copy the HTML and JavaScript documents from the Windows Phone project to the Android…

image

…or iOS project…

image

Et voila we’re done.

image

Advertisements
This entry was posted in AJAX, Bing Maps, PhoneGap, Windows Phone and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s