Mobile Map route from google server
Hello. I am trying to make a map that will display a route that is not stored on the phone, but one that is received from a service.
I have some experience at this using this link witch if put in the address bar will generate a .kml file, that containes at the end the coordinates of the route.
I've tried making a xhr in Titanium and making a GET request to that link, but if I try to take the responseXML or Text, I stumble upon a html page.
Can someone please point me in the right direction?
Thanks in advance.
5 Answers
-
I've got this working by adding a parameter "output=kml" to the link, and if someone is interested, here is the code:
data = []; var url = "http://maps.google.com/?saddr=" + origin + "&daddr=" + destination + "&doflg=ptk&hl=en&output=kml" xhr = Titanium.Network.createHTTPClient(); xhr.open('GET',url); Ti.API.info('>>> go get data for Rgeocode! ...URL: '+url); xhr.onload = function(){ // Now parse the XML var xml = this.responseXML; var points = []; var coords = xml.documentElement.getElementsByTagName("LineString"); for(var cc=0; cc < coords.length; cc++) { var line = coords.item(cc); var str = line.firstChild.text.split(" "); for(dd = 0; dd < str.length; dd++) { var loc = str[dd].split(','); if(loc[0] && loc[1]) { points.push({latitude: loc[1], longitude: loc[0]}); } } } var route = { name:"boston", points:points, color:"red", width:4 }; // add a route map.addRoute(route); }; xhr.send();
-
I have updated the code, as the route was not very accurate. Now it's decoding the polylines and adding all their points to the point array:
The first part of the
onload
should be replaced with this:var xml = this.responseXML, points = [], steps = xml.documentElement.getElementsByTagName("step"), totalSteps = steps.length; for(var i = 0; i < totalSteps; i++) { var polylineString = steps.item(i).getElementsByTagName("polyline").item(0).getElementsByTagName("points").item(0).text, decodedPolyline = decodeLine(polylineString); for (var j = 0; j < decodedPolyline.length; j++) { if (decodedPolyline[j] != null) { points.push({ latitude : decodedPolyline[j][0], longitude : decodedPolyline[j][1] }); } } }
And the decoding function:
function decodeLine(encoded) { var len = encoded.length; var index = 0; var array = []; var lat = 0; var lng = 0; while (index < len) { var b; var shift = 0; var result = 0; do { b = encoded.charCodeAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.charCodeAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); lng += dlng; array.push([lat * 1e-5, lng * 1e-5]); } return array; }
-
After trying both code snippets, I got the
HTTPClient
with emptyresponseXML
property. Then I decided to go on my own and I ended up with this code. Note that the URL format is different, and I have added annotations aswell as a travel mode to the settings.Ti.Geolocation.getCurrentPosition(function(evt) { var origin = String(evt.coords.latitude + ',' + evt.coords.longitude), travelMode = 'walking', destination = String(yourLatitude + ',' + yourLongitude), url = "http://maps.google.com/maps/api/directions/xml?mode=" + travelMode + "&origin=" + origin + "&destination=" + destination +"&sensor=false"; xhr = Titanium.Network.createHTTPClient(); xhr.open('GET',url); Ti.API.info('>>> go get data for Rgeocode! ...URL: ' + url); xhr.onload = function(e){ var xml = this.responseXML, points = [], steps = xml.documentElement.getElementsByTagName("step"), totalSteps = steps.length; for (var i=0; i < totalSteps; i++) { var startLocation = steps.item(i).getElementsByTagName("start_location"); startLatitude = startLocation.item(0).getElementsByTagName("lat").item(0).text, startLongitude = startLocation.item(0).getElementsByTagName("lng").item(0).text; points.push({latitude:startLatitude, longitude:startLongitude}); } // Get last point and add it to the array, as we are only parsing <start_location> var finalLocation = steps.item(totalSteps - 1).getElementsByTagName("end_location"), finalLatitude = finalLocation.item(0).getElementsByTagName("lat").item(0).text, finalLongitude = finalLocation.item(0).getElementsByTagName("lng").item(0).text; points.push({latitude:finalLatitude, longitude:finalLongitude}); // Create route and annotations var route = { name:"bonVoyage", points:points, color:"blue", width:6 }, startAnnotation = Ti.Map.createAnnotation({ pincolor: Ti.Map.ANNOTATION_RED, latitude: points[0].latitude, longitude: points[0].longitude, title: 'Current location' }), endAnnotation = Ti.Map.createAnnotation({ pincolor: Ti.Map.ANNOTATION_RED, latitude: points[points.length - 1].latitude, longitude: points[points.length - 1].longitude, title: 'Destination' }); // Add elements mapView.addRoute(route); mapView.addAnnotation(startAnnotation); mapView.addAnnotation(endAnnotation); }; xhr.send(); });
Also note that you have to set your destination coords, and have a
mapView
object created beforehand.By the way, there is a bug in 1.7.x SDK that makes the route dissapear when you reach certain level of zoom, aswell as while you scroll the map. With 1.8.0, the scrolling part is still present but the zoom works ok.
-
So this basically adds a route overlay to your existing mapview? Right now I'm having to hack it and open up the native app which works, but looks unprofessional.
-
ha