Developing Android Applications with Adobe AIR [58]
Google Maps 5
Google Maps 5 was released in December 2010. It provides 3D building rendering, dynamic vector-based map drawing, and offline reliability. If you would like to see it supported in AIR, file a software request on the Adobe site, http://www.mobilecrunch.com/2010/12/16/google-maps-5-with-3d-buildings-now-available-for-android/.
EXIF Data and the Map Object
In Chapter 9, we saw how a JPEG image stores location information if the user allows that feature. Let’s look at an example in which the user can choose an image from the camera roll, read its location information, and display the corresponding map:
NOTE
For an explanation on the use of the CameraRoll API and Kenichi Ishibashi’s EXIF library, please review Chapter 9.
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.LatLng;
import com.google.maps.MapType;
import com.google.maps.overlays.Marker;
import com.google.maps.overlays.MarkerOptions;
import flash.events.Event;
import flash.events.MediaEvent;
import flash.media.CameraRoll;import flash.net.URLRequest;
import jp.shichiseki.exif.*;
public static KEY:String = YOUR_API_KEY;
public static SITE:String = YOUR_SITE;
var cameraRoll:CameraRoll;
var exifLoader:ExifLoader;
var map:Map;
Create your Map object as before:
map = new Map();
map.url = SITE;
map.key = KEY;
map.sensor = "false";
map.setSize(new Point(stage.stageWidth, stage.stageHeight));
map.addEventListener(MapEvent.MAP_READY, onMapReady);
addChild(map);
Get an image from the device Gallery using the CameraRoll API:
function onMapReady(event:MapEvent):void {
map.setCenter
(new LatLng(40.736072, -73.992062), 14, MapType.NORMAL_MAP_TYPE);
if (CameraRoll.supportsBrowseForImage) {
var camera:CameraRoll = new CameraRoll();
camera.addEventListener(MediaEvent.SELECT, onImageSelected);
camera.browseForImage();
}
}
After the user selects an image, create an instance of the ExifLoader class and pass it the photo url. It will load the image and read its EXIF data:
function onImageSelected(event:MediaEvent):void {
exifLoader = new ExifLoader();
exifLoader.addEventListener(Event.COMPLETE, onExifRead);
exifLoader.load(new URLRequest(event.data.file.url));
}
If the image contains geolocation information, it is used to draw the map and a marker at the exact location:
function onImageLoaded(event:Event):void {
var exif:ExifInfo = reader.exif;
if (exif.ifds.gps) {
var gpsIfd:IFD = exif.ifds.gps;
var exifLat:Array = gpsIfd["GPSLatitude"] as Array;
var latitude:Number = shorten(exifLat, gpsIfd["GPSLatitudeRef"]);
var exifLon:Array = gpsIfd["GPSLongitude"] as Array;
var longitude:Number = shorten(exifLon, gpsIfd["GPSLongitudeRef"]);
var marker:Marker;
var parts:Array;
marker = new Marker(new LatLng(latitude, longitude));
map.addOverlay(marker);
map.setCenter(new LatLng(latitude, longitude));
}
}
function shorten(info:Array, reference:String):Number {
var degree:Number = info[0] + (info[1]/60) + (info[2]/3600);
// position from Greenwich and equator
if (reference == "S" || reference == "E") {
degree * -1;
}
return degree;
}
The speed Property
We are all familiar with a car speedometer, which tells you how fast you are driving. Although not nearly as precise, geolocationEvent has a speed property which you can use in some applications. You can imagine an application for parasailing, parachuting, or skiing, or if you prefer to remain on the ground, a measuring tool for a remote-controlled toy.
The speed is returned in meters/second. It is a good unit for small-distance measurement. To convert to kilometers/hour, use:
event.speed * 3.6;
If you are not familiar with the metric system, convert the speed to feet/second as follows:
event.speed * 3.2808399;
To convert to miles/hour, use:
event.speed * 2.23693629; // or (event.speed*3600)/1609.344
Conclusion
Geolocation has inspired the development of many kinds of applications. Here are just a few:
Foursquare is a geo-based mobile phone application