Posted on by | Posted in Mobile Blog, Tutorial | Tagged , , ,

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.



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

  1. Pingback: Routing / Driving directions on Android – Part 2: Draw the route | Mobile Solutions Blog

  2. Ally says:

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

    cheers


  3. David Linsin David Linsin says:

    Hi Ally,

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


  4. CJ says:

    Hi David,

    do you still think about open sourcing the code??

    Regards

    CJ


  5. Farhan says:

    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


  6. Tobias Knell Tobias Knell says:

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


  7. shopno nill says:

    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


  8. zodiacq says:

    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


  9. Tobias Knell Tobias Knell says:

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


  10. scamexdotexe says:

    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…


  11. Deepchand Singh says:

    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


  12. Rajesh says:

    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. . .:)


  13. Tobias Knell Tobias Knell says:

    Sorry, I forgot to mention it, it’s a String.


  14. Tobias Knell Tobias Knell says:

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


  15. Tobias Knell Tobias Knell says:

    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.


  16. Diarmuid McCarthy says:

    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;
    }


  17. tyegah says:

    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?


  18. Jed says:

    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


  19. Tobias Knell Tobias Knell says:

    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:
    JSONObject directions = new JSONObject(stringResponse);
    List<GeoPoint> route = new ArrayList<GeoPoint>();
    route = decode(directions.getJSONArray("polylines").getJSONObject(0).getString("points"));


  20. Chandra sekhar says:

    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


  21. Tobias Knell Tobias Knell says:

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


  22. Haitham Elsheshtawy says:

    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


  23. coolspirits says:

    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!!


  24. Tobias Knell Tobias Knell says:

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


  25. coolspirits says:

    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.


  26. Tobias Knell Tobias Knell says:

    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


  27. coolspirits says:

    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!!!!


  28. Tobias Knell Tobias Knell says:

    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.


  29. coolspirits says:

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


  30. coolspirits says:

    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! :)


  31. Tobias Knell Tobias Knell says:

    @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


  32. krunal says:

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


  33. momoci99 says:

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


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>