Routing / Driving directions on Android – Part 1: Get the route

Complementary to Sebastian’s posts about how to navigate with the MapView and how to add customized overlays to it, I want to show you, how you display the route between two points.
Well, the whole thing wouldn’t be a pain now, if google hadn’t removed the DrivingDirection class since API 1.0, with which you could solve this problem in no time and with just a few lines of code. But because they did remove it, we have to go through a little bit more trouble.

Getting started

First you have to realize, if you only need the coordinates of the route, or also driving directions like “go left on this street, drive right on that street…”.
The first step in both cases is to get the two locations between which the routing should happen. In our case we wanted to show the route from the current location of the user to our office, so one of the points is fixed:

synyxGeoPoint = new GeoPoint(49002175, 8394160);

And the user location is also quite easy to get:

locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
Location lastKnownLocation =
locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true));

With this we get the last known, accurate location of the user. So all there is left now, is to get the route.

Getting the geopoints from google maps

Kml (with driving directions)

If you need the driving directions, you can build yourself a url like this one to get a kml file with all the information:
http://maps.google.com/maps?f=d&hl=en&saddr=9.18333,48.7667&daddr=8.394160,49.002175&ie=UTF8&0&om=0&z=20&output=kml
(For the list of parameters of google maps, see here: mapki.com)
Here’s how we did it:

public String getUrl(GeoPoint src, GeoPoint dest){
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.google.com/maps?f=d&hl=en");
urlString.append("&saddr=");
urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
urlString.append(",");
urlString.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
urlString.append("&daddr=");// to
urlString.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
urlString.append(",");
urlString.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
urlString.append("&ie=UTF8&0&om=0&output=kml");
return urlString;
}

The file you get from this url looks like this:

Hohenheimer Str./B27 to Karlstraße/L561
....
Head southeast on Hohenheimer Str./B27 toward Bopserwaldstraße Continue to follow B27
....
9.183560,48.766820,0.000000 9.183690,48.766670,0.000000 9.183640,48.766480,0.000000 9.183470,48.766380,0.000000
....

(the first number of each pair is the longitude, the second the latitude)
To convert them to GeoPoints use:

GeoPoint geoPoint = new GeoPoint((int)(Double.parseDouble(latitude[0])*1E6),(int)(Double.parseDouble(longitude[0])*1E6));

JSON (without driving directions)

If you don’t need the driving directions, you can save a few kilobytes by changing the output parameter to output=dragdir (else it’s exactly the same url as above) , which delivers you a json string with encrypted geopoints.
again an example of what the server returns:

{tooltipHtml:" (572x26#160;km / 5 hours 14 mins)",polylines:[{id:"route0",points:"se}bIgcwt@BSzA_D??Xh@dC|G??hDlIpBzFrAvC`@`BZjCV|@nApBtDvEx@rA| .....

So as you can see, you can’t just parse the string and get the geopoints out of it. You first have to decode them. Here’s a method that solves this for you (algorithm from http://facstaff.unca.edu/) :

// get only the encoded geopoints
encoded = encoded.split("points:"")[1].split("",")[0];
// replace two backslashes by one (some error from the transmission)
encoded = encoded.replace("\\", "\");
//decoding
List poly = new ArrayList();
		int index = 0, len = encoded.length();
		int lat = 0, lng = 0;
		while (index < len) {
			int b, shift = 0, result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;
			shift = 0;
			result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;
			GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6), (int) (((double) lng / 1E5) * 1E6));
			poly.add(p);
		}

Getting the geopoints from open streetmap

You can also get the geopoints from open streetmap. It’s quite the same procedure, so i don’t write it all again.
Here you can see for yourself: YOURS Routing_API

What’s in the next post

That’s it for today, in the next post i will show you how to draw the route on your MapView properly.

Kommentare

  1. Hi Tobias, I am trying to get the navigation directions from google maps in my app in real time i.e I should be able to fetch the string "Turn Right" in my app. Is there a way to do it?

  2. Thank you for Tobias Knell
    You saved my time!!!!!!

  3. Hi, i am new to android, and cant understand your code properly, will you provide zip of fuul snipt of code..

  4. @coolspirits: Sorry, but I can't help everyone with every little problem. Try to debug it, and you will find the reason why it doesn't work :P

  5. hey Tobias,
    can u run this code (on the link below ) on your machine , and let us know if its working alright ?!! coz here, the launcher keeps on stopping!!
    http://stackoverflow.com/questions/11745314/why-retrieving-google-directions-for-android-using-kml-data-is-not-working-anymo
    thanks in advance! :)

  6. okay.... Tobias, dude, thanks for your time! :)
    we will try to figure it out.

  7. Tobias, we DONT want to use the "INTENT" thing! ....
    here, consider two text boxes of source and destination, the user enters in string ...and hits enter ..... the route is displayed on the map! ...we cannot use this URI thing because we would be storing these routes for further processing....!!
    if we could get the routes and alternative paths of the fixed source and destination!!!!!! that would be AWESOME!!!!
    and also we have tired all the codes given on the stackoverflow site for the current problem ..... but they don't work.. the launcher keeps on crashing!!!!

  8. Hey Tobias.... you got it all wrong....we were trying to say that we don't want to do the url thing inside our app (e.g pasting this , inside our code
    String uri = "http://maps.google.com/maps?saddr=" + Utils.getLatitude(ShowDetails.this)+","+Utils.getLongitude(ShowDetails.this)+"&daddr="+userLatitude+","+userLongitude;
    Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(uri));
    intent.setClassName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity");
    startActivity(intent);
    Can u please tell us the code for using the google directions service i.e we enter the source and destination ...and the path is displayed on the google maps.. and we also need the alternative routes!!
    We just want to direction service in our app. without using the URI thing..........!!
    thanks in advance.

  9. If you don't want to access a web routing service and don't want to use intents for some routing app, I don't think there's another possibility than do the routing yourself. Maybe theres some library for this, but I don't know one.

  10. Oh okay, sorry then.
    I haven't used the directions api yet, but maybe this could work:
    http://stackoverflow.com/questions/2662531/launching-google-maps-directions-via-an-intent-on-android

  11. Hi,
    can u plz tell how to show route between two points (source and destination ) also alternative routes …… (without using website or kml file) we want this functionality to be embedded in our application!! PLZ REPLY SOON!!

  12. @coolspirits: without websites? here, for starters: http://en.wikipedia.org/wiki/Graph_theory

  13. Dear,
    For using JSON, kindly go to this link, it will help you to download JSON file , Parse it and finally Draw the path on the map
    Link --> http://stackoverflow.com/questions/11323500/google-maps-api-version-difference

  14. It does, if you change the parameter in output=json ...

  15. do u have sample code of this
    and r u sure the url will give json i loaded in browser its connecting to google maps

  16. How do you get from the built URL to the encoded string?
    I can build the URL and it returns the JSON data (in a file when I just paste it in Firefox) but in code it's not intuitive to me how to get this done. Did I miss something or is this something basic I should know (I'm fairly new so I could be missing something simple).
    Jed

  17. Yup, apparently, the KML output no longer works.
    For the JSON output, just parse for the "polylines", get the encoded Points out of it and let the code above decode it.
    Something like:
    <code>JSONObject directions = new JSONObject(stringResponse);
    List<GeoPoint> route = new ArrayList<GeoPoint>();
    route = decode(directions.getJSONArray("polylines").getJSONObject(0).getString("points"));</code>

  18. Unfortunately google doesnt support the KML file anymore. Can you give an example of how to extract the lat and long from JSON output instead?

  19. Anyone wishing to find the route to multiple locations just send in multiple queries to google.
    I.E.
    Use this code but just add stop 1 to stop2, stop2 to stop3, stop 3 to stop 4 ect....
    It will get you the directions through all those positions. Simples!!!!
    urlString.append("http://maps.google.com/maps?f=d&hl=en");
    public String getUrl(GeoPoint src, GeoPoint dest){
    StringBuilder urlString = new StringBuilder();
    urlString.append("http://maps.google.com/maps?f=d&hl=en");
    urlString.append("&saddr=");
    urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
    urlString.append(",");
    urlString.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
    urlString.append("&daddr=");// to
    urlString.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
    urlString.append(",");
    urlString.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
    urlString.append("&ie=UTF8&0&om=0&output=kml");
    return urlString;
    }

  20. Can U please tell me about the KML file limits ??
    Actually in my project I need to find the locations between two places . So which would be a better option using JSON or KML ???
    Thank You In Advance. . .:)

  21. I don't know more about it, either. It was an internal project and I didn't spend that much time on it, so I didn't have the time to go into the maps api in detail.

  22. Hi Knell,
    Thanks for sharing this blog.
    It will be great if you will help me out in getting multiple route between two location.
    please update about this on your blog or at deep21c@gmail.com.
    Thanks,
    Deepchand Singh

  23. I didn't dig any deeper in the maps api, so I also can't help you there.

  24. hey, i tried your code...but I wanna know what "encode" means?
    What I mean is that, is it a class? a variable or something? please help me...

  25. Sorry, I forgot to mention it, it's a String.

  26. dear master, why my draw routing can't full draw path, just little bit draw to destination? especially if distance about 200km, are google have limited distance?? please help, im newbie

  27. I also happened to encounter this problem. Apparently, they have a limit on the KML file size.

  28. please..can you upload the full code as zip file.I think that must be better for me or others to understand and compile the code...thank you

  29. i am trying using the URL: http://maps.google.com/maps?f=d&hl=en&saddr=23.713656,90.437135
    &daddr=23.710091,90.434399&ie=UTF8&0&om=0&output=kml. but null string is returned. what is the problem

  30. Apparently some error in google maps, try using a slightly different position.

  31. Hi David,
    do you still think about open sourcing the code??
    Regards
    CJ

  32. Interesting, do you have the project/source available to download to test in the emulator?
    cheers

  33. Hi Ally,
    we are thinking about open sourcing the code. In case we do, check back here to know about it firsthand.