Developing Virtual Earth iPhone Applications with Objective-C

image You’ve been waiting for this post. If you’ve tried doing any iPhone development with Virtual Earth you’ve probably been swearing up a storm, beating down your computer, and lost hours of sleep wondering how Loopt, Weather Central and now NMobile got their iPhone apps working. Well, Colin Cornaby from Consonance Software may just be your new best friend. He’s the one who build the NMobile application I posted to the blog yesterday - “Mobile Speed Trap Mapping with iPhone” – which uses 100% supported code from Microsoft Virtual Earth to get the road and aerial map tiles via the Virtual Earth Web Services and use them for your iPhone applications.

image

Before we begin I want to address the challenges so you have an appreciation for just how HUGE this it.

  • First, you’ll have to write against the Virtual Earth Web Service which communicates using SOAP XML, so you can’t use JavaScript. Um, ok.
  • Next, Apple forgot to include iPhone support for SOAP (oops), so you’ll have to create request packets and parse response packets to and from the service, respectively.
  • Then, with the Virtual Earth Imagery Service you only get a single quad key back (a part of the tile URL); and, with that you need put together the entire tile URL.
  • Next, you’ll have to reconstruct the Virtual Earth tile pyramid extrapolated out from the quad key returned from VEWS. The tile pyramid schema is documented in the MSDN Technical Article, “Virtual Earth Tile System.”
  • Finally, you’ll have to put it all together into a pretty iPhone-ish interface.

Wow! This sounds treacherous (but very doable). And, well, it would be treacherous but there’s always someone out there who has the drive to make stuff happen. Colin from Consonance just so happens to be that someone you’ve been looking for. Ready?

Consonance Software has created the VirtualEarthKit for ObjC / Cocoa developers. The VirtualEarthKit contains a set of APIs that you can reference for your iPhone projects to develop iPhone applications using Microsoft Virtual Earth. So, download the VirtualEarthKit (in SVN Repository | trunk | English.lproj | InfoPlist.strings), add a reference to the library from your project, then access the VirtualEarthKit APIs which automatically wrap the Virtual Earth Web Service requests and parse the responses for your application. The VirtualEarthKit supports many of the VEWS features, in addition to getting maps, including geocoding, reverse geocoding, adding pushpins and user profile elements (device type and distance unit enumerations).

Here’s a little sample to whet you Cocoa / ObjC devs on how to access VE tiles:

//
// VEImageryService.m
// MapView
//
// Created by Colin Cornaby on 10/12/08.
// Copyright 2008 __Consonance Software__. All rights reserved.
//

#import "VEImageryService.h"
#import "VEImageryResult.h"
#import "VEGetMapURIResponse.h"
#import "VEServicePrivate.h"

@implementation VEImageryService

-(VEServiceResponse *)getImageryMetadata:(VEImageryMetadataRequest *)request
{
xmlNodePtr xmlRequest;
[request serializeToXMLQuery:&xmlRequest];
NSString *server = @"https://dev.virtualearth.net/webservices/v1/imageryservice/imageryservice.svc";
    if(self.realm==kVEStagingRealm)
server = @"https://staging.dev.virtualearth.net/webservices/v1/imageryservice/imageryservice.svc";
    xmlNodePtr result = [super sendVERequestWithBody:xmlRequest action:@"https://dev.virtualearth.net/webservices/v1/geocode/contracts/IImageryService/GetImageryMetadata" server:[NSURL URLWithString:server] error:nil];
xmlNodePtr body = nil;
for(body = result->children; body; body = body->next)
{
if(!strcmp((char *)body->name, "GetImageryMetadataResult"))
break;
}
VEServiceResponse *response = nil;
if(body)
response = [[VEServiceResponse alloc] initWithXMLNode:body resultClass:[VEImageryResult class]];
return response;
}

-(VEGetMapURIResponse *)getMapURI:(VEGetMapURIRequest *)request
{
xmlNodePtr xmlRequest;
[request serializeToXMLQuery:&xmlRequest];
NSString *server = @"https://dev.virtualearth.net/webservices/v1/imageryservice/imageryservice.svc";
    if(self.realm==kVEStagingRealm)
server = @"https://staging.dev.virtualearth.net/webservices/v1/imageryservice/imageryservice.svc";
    xmlNodePtr result = [super sendVERequestWithBody:xmlRequest action:@"https://dev.virtualearth.net/webservices/v1/imagery/contracts/IImageryService/GetMapUri" server:[NSURL URLWithString:server] error:nil];
xmlNodePtr body = nil;
for(body = result->children; body; body = body->next)
{
if(!strcmp((char *)body->name, "GetMapUriResult"))
break;
}
VEGetMapURIResponse *response = nil;
if(body)
response = [[VEGetMapURIResponse alloc] initWithXMLNode:body resultClass:[VEImageryResult class]];
return response;
}

@end

A little about the VirtualEarthKit from the Consonance web site:

VirtualEarthKit is a framework to allow Cocoa developers to communicate with Microsoft Virtual Earth . Microsoft Virtual Earth provides a wide range of services, including geocoding, reverse geocoding, map imagery, route guidance, and business lookup.

Dependencies for VirtualEarthKit have also been minimized in order to keep VirtualEarthKit portable for different OS X platforms. VirtualEarthKit uses LibXML for constructing all SOAP requests. To facilitate clean integration with Cocoa and the iPhone SDK, VirtualEarthKit requires the CoreLocation framework. Fortunately, VirtualEarthKit for Mac OS X uses Philippe Casgrain's re-implementation of CoreLocation for Mac OS X . Integration with CoreLocation allows developers for the iPhone platform to use VirtualEarthKit cleanly with the phone's GPS implementation.

Okay, so this is just game changing for mobile mapping. iPhone has completely taken off and I receive inquiries every day for iPhone developer support and licensing. Well, let’s get developing! Can adding maps to your iPhone app get any easier now? If you still need a license, contact me so we can get that out of the way. Download the VirtualEarthKit now and get cranking!

CP

Comments

  • Anonymous
    November 13, 2008
    Great work guys. I hope you get to create some cool apps.

  • Anonymous
    November 15, 2008
    This is awesome, functionality of this sort should be useful to any developer using location based services (no need to exit your .app to get useful mapping anymore!).   However, it is still a bit daunting for developers new to the platform -- is the image above compiled from the code snippet here?  If possible, I'd love to take a look at the whole code used to build that image - it looks like many elements that would be useful to developers trying to paste this into apps are already present and perhaps the code may be useful in its entirety?  If this is possible, it would be greatly appreciated!

  • Anonymous
    November 19, 2008
    The comment has been removed

  • Anonymous
    March 09, 2009
    I agree, this is awesome! Thank you. Quick question, the sample desktop app seems to retrieve a static image. When folks have implemented this on the iPhone did they have to calculate which tiles to fetch next, or did I miss that functionality in the VEKit? Thanks again!

  • Anonymous
    March 11, 2009
    The comment has been removed

  • Anonymous
    March 16, 2009
    I have tried using this framework for the iPhone but I've had trouble when creating my project. I get this error. dyld: Library not loaded: /Users/ryan/Library/Frameworks/VirtualEarthKit.framework/Versions/A/VirtualEarthKit  Referenced from: /Users/ryan/Library/Application Support/iPhone Simulator/User/Applications/7E47FE9A-FFFA-4C0B-ADE2-CFE4382C6673/Hello.app/Hello  Reason: image not found Any ideas someone might be able to help me with? Thanks, Ryan

  • Anonymous
    May 28, 2010
    Thank you very much for your article. It's great!! I have a commercial question: I need to use only geocode service, is it free?

  • Anonymous
    May 28, 2010
    Thank you very much for your article, it's great! I have a commercial question: I need to use Geocode service, is it free?