At a glance Main Projects Tutorials Resume



Migrating to Javascript from the Google Maps API for Flash Using Adobe AIR

Fri, 2 Dec 2011 22:59:58 EST

Running the google maps v3 javascript API in Adobe AIR.
Google recently depreciated the maps API for Flash, which according to their terms of service looks like will be completely dead within three years. Despite everyone freaking out about Adobe's recent announcements, Adobe AIR will still be supported across several platforms. In the museum industry I've used Adobe AIR on many projects. Utilizing certain techniques available in AIR you can implement the fully supported Javascript V3 Google Maps API and have close to the same functionality as the Flash API.

The Adobe AIR HtmlLoader classes provide access to a built-in webkit browser that has Javascript rendering capability. The HtmlLoader is the avenue that I used to implement the Javascript V3 library. Using AIR you can make calls to Javascript functions, and Javascript can in-turn preform call-backs into your Actionscript functions if you set them up properly and pay consideration to the AIR security sandbox. The HtmlLoader can properly render the Google Maps in the browser, so there really isn't much work that needs to be done.

I'm going to walk you through how to get an example working that uses the directions service to request directions between two points with a way-point between them. I wanted to use this service because I initially had trouble with the google.maps.DirectionsRoute object because it contains a lot of great data and I made a tiny mistake when initially trying to parse it in AS3.

The initial geocoded location of a museum in Texas.
The methodology I use loads a HTML file into AIR/Flash dynamically during run-time then orders the HTML Loader to render that. I took this approach because I wanted an intermediate level of code in case the Javascript API ever changes.

Step one is to get a html file working that that will render the Google Maps API. I have this html file set so it will render the latitude and longitude of one of my favorite museums I've been lucky to work on, the National Museum of the Pacific War in Fredericksburg, Texas, U.S. When the page loads, the Javascript function initialize is called, which uses the geocoding service; which in Javascript returns the results, where I extract the latitude and longitude and render the map. This initial geocoding is all done in the Javascript.

Here is an excerpt from the html of some of the javascript functions that help get the process going:

  1.   var map = null;
  2.   var geoCoder = null;
  3.   var directionService = null;
  4.   var directionsDisplay = null;
  5.  
  6.   // First, make a request using the cool geocoding service to get the latitude and longitude
  7.   function initialize() {
  8.     var initialAddress = "National Museum of the Pacific War 340 East Main Street, Fredericksburg, TX 78624";
  9.          
  10.     geocodeStringAddress(initialAddress);
  11.    
  12.   }
  13.   function initializeMap(_LatLon) {
  14.         var myOptions = {
  15.               zoom: 8,
  16.               center: _LatLon,
  17.               mapTypeId: google.maps.MapTypeId.ROADMAP
  18.             };
  19.            
  20.             map = new google.maps.Map(document.getElementById("map_canvas"),
  21.                 myOptions);
  22.   }
  23.   <!-- Handles the result of a geocode -->
  24.   function handleGeocodeResult(results, status) {
  25.  
  26.       if (status == google.maps.GeocoderStatus.OK) {
  27.        
  28.             try {
  29.                 // This calls flash with the resuls check your traces
  30.                 window.JSnewGeocodeData(results);
  31.                 // Call this so we get a map going
  32.                 initializeMap( results[0].geometry.location );
  33.             } catch (err) {
  34.                 // Sink the error that was trying to call an AIR function
  35.             }
  36.       } else {
  37.             try {
  38.                 // Calls a function in AS3 that references the error
  39.                 window.JSgeocodeError(status);
  40.             } catch (err) {
  41.                 // Sink it
  42.             }
  43.       }
  44.   }
  45.   <!-- Can call this from AIR using the DOM for geocoding stuff..weeeeee -->
  46.   function geocodeStringAddress(_stringAddress) {
  47.     if(geoCoder == null) {
  48.         geoCoder = new google.maps.Geocoder();
  49.     }
  50.     geoCoder.geocode( { 'address': _stringAddress}, handleGeocodeResult );
  51.   }


After you get things initialized, the next step is to fill in the rest of the Javascript functions needed to work with your desired maps functionality. Make sure your javascript is error free, then we can go over to the Flash/AIR side of things. The full html file(available in the sample download) includes the rest of the javascript functions that are needed to work with the cool Directions service.

In Flash/AIR, I first load the html (named GoogleMapsV3_JSFunctions.html) as a big string using a URLLoader.
  1. private var AbstractDataLoader:URLLoader = new URLLoader();
  2. private var theBrowser:HTMLLoader;
  3.  
  4. //..... further down in the code
  5. AbstractDataLoader.addEventListener(Event.COMPLETE, HandleData, false, 0, true);
  6. // Start loading the html
  7. AbstractDataLoader.load(new URLRequest("GoogleMapsV3_JSFunctions.html"));
  8.  
  9. private function HandleData(e:Event):void {
  10.      e.currentTarget.removeEventListener(Event.COMPLETE, HandleData);
  11.  
  12.     var notXML:String = e.target.data;
  13.     trace("Text loaded - rendering in browser");
  14.     theBrowser.loadString(notXML);
  15. }

When the html is loaded as a plain string, I tell the htmlLoader to render it using the loadString method.

The way you call javascript from AIR and AIR from Javascript are as follows:

In Flash to call Javascript and allow callbacks, you preform certain operations on the HTMLLoader instance. To allow the callbacks, you need to set them up:
  1. // If set to True wont load external scripts in html
  2. theBrowser.placeLoadStringContentInApplicationSandbox = false;
  3.  
  4. // These direct where function calls from Javascript should go
  5. theBrowser.window.JSnewGeocodeData = JSnewGeocodeData;
  6. theBrowser.window.JSgeocodeError = JSgeocodeError;
  7. theBrowser.window.JSnewDirectionData = JSnewDirectionData;
  8. theBrowser.window.JSnewDirectionDataError = JSnewDirectionDataError;
  9.  
  10. // Example of calling a function on the htmlloader use .window.functionname
  11. theBrowser.window.calculateEntireRoute(tripArr);


In Javascript, after we have setup the callbacks in AIR/Flash we can call into the code by doing something like this:
  1. // Use window.functionname in Javascript
  2. window.JSnewDirectionDataError(_status);


The map with directions rendered.
If you run the examples and click the button in the lower right labled "Map Route", it will call a javascript function from inside of AIR that uses the Directions service to obtain, and map a route between my current town, Dewitt, Michigan and Fredericksburg, Texas with a stop at the Turkey Hill Experience in Columbia PA on the way.

When you click the "Map Route" button it in-turn calls the javascript function, calculateEntireRoute to preform a directions service call with three addresses. Once that returns in Javascript to the function handleAddressResults, it makes a call-back into Flash to the function JsnewDirectionData. From there in Flash you'll see I trace out all the directions, then pass the results object back to javascript; where the API finally renders the map with directions.

I've provided downloads of the entire example in CS4 Fla, Flash Builder 4.5, and FlashDevelop 4 which will hopefully satisfy the majority of you. They are all contained in the zip file.:

DOWNLOAD THE SOURCE FILES HERE


Best of luck on your migrations. If you have questions, please post them in the comments and I'll do my best to help you out.

Charles Palen has been involved in the museum and visitor center industry for several years. He works as a senior interactive developer at Transcending Digital where he can be hired for your next contract project. Charles expertise covers the areas of A/V integration, touchscreen programming, creation of original devices, and much more. Charles created Technogumbo as a way to share lessons learned while making original products.

Comments

Bruce
Bruce
December 5, 2011 4:05 pm

Pretty cool. Glad to see there is still a way of using the Google Maps API in AIR applications. The mapping is so robust, it would be a shame to lose that as a resource to AIR for the many mapping applications that museums and visitor centers need.

Name:

Message:

Avatar:
bomb avatar music player avatar email avatar nerdy tux avatar gimp avatar red hat avatar red time avatar mysterious man avatar tan smiley avatar devil smiley avatar pipe guy avatar

Complete the Re-Captcha to Post Your Message: