Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to draw route directions google maps API V2 from current location to destination

How to draw route direction from current location to destination which (latitude and longitude), i have code as below:

import android.os.Bundle; import com.actionbarsherlock.app.SherlockActivity;  import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions;  public class DetailMapActivity extends SherlockActivity {     private GoogleMap map;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main_detail_map);          LatLng TO_DESTINATION = new LatLng(-6.33438, 106.74316);          map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))                 .getMap();         map.setMyLocationEnabled(true);          map.addMarker(new MarkerOptions().position(TO_DESTINATION).title("Destination Title")                 .snippet("Destination Description"));          map.moveCamera(CameraUpdateFactory.newLatLngZoom(TO_LOCATION, 40));          map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);     } } 

I want to draw from current location by provider network or gps, and then draw the route by driving to destination.

I'm using android google apis V2.

Thanks for your help.

like image 939
Dave Jackson Avatar asked Jan 21 '13 17:01

Dave Jackson


People also ask

Can you drag route on Google Maps Android?

To choose an alternate route, either click on a greyed-out route on the map or click on one of the other routes listed on the left-hand side menu. Note that you can also change routes by clicking on one and dragging it so that the directions will take you via certain roads.

How do I use Google Directions API on Android?

You must have at least one API key associated with your project. Go to the Google Maps Platform > Credentials page. On the Credentials page, click Create credentials > API key. The API key created dialog displays your newly created API key.


2 Answers

This works great for me:
It's not my code, I took it from a great answer at stackoverflow but I can't find this answer now, so here is the code:

Add this class to your project:

package ...;  import java.io.InputStream; import java.util.ArrayList;  import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;  import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList;  import com.google.android.gms.maps.model.LatLng;  import android.content.Context; import android.util.Log;  public class GMapV2Direction {     public final static String MODE_DRIVING = "driving";     public final static String MODE_WALKING = "walking";      public GMapV2Direction() {     }      public Document getDocument(LatLng start, LatLng end, String mode) {         String url = "http://maps.googleapis.com/maps/api/directions/xml?"                 + "origin=" + start.latitude + "," + start.longitude                 + "&destination=" + end.latitude + "," + end.longitude                 + "&sensor=false&units=metric&mode=driving";         Log.d("url", url);         try {             HttpClient httpClient = new DefaultHttpClient();             HttpContext localContext = new BasicHttpContext();             HttpPost httpPost = new HttpPost(url);             HttpResponse response = httpClient.execute(httpPost, localContext);             InputStream in = response.getEntity().getContent();             DocumentBuilder builder = DocumentBuilderFactory.newInstance()                     .newDocumentBuilder();             Document doc = builder.parse(in);             return doc;         } catch (Exception e) {             e.printStackTrace();         }         return null;     }      public String getDurationText(Document doc) {         try {              NodeList nl1 = doc.getElementsByTagName("duration");             Node node1 = nl1.item(0);             NodeList nl2 = node1.getChildNodes();             Node node2 = nl2.item(getNodeIndex(nl2, "text"));             Log.i("DurationText", node2.getTextContent());             return node2.getTextContent();         } catch (Exception e) {             return "0";         }     }      public int getDurationValue(Document doc) {         try {             NodeList nl1 = doc.getElementsByTagName("duration");             Node node1 = nl1.item(0);             NodeList nl2 = node1.getChildNodes();             Node node2 = nl2.item(getNodeIndex(nl2, "value"));             Log.i("DurationValue", node2.getTextContent());             return Integer.parseInt(node2.getTextContent());         } catch (Exception e) {             return -1;         }     }      public String getDistanceText(Document doc) {         /*          * while (en.hasMoreElements()) { type type = (type) en.nextElement();          *           * }          */          try {             NodeList nl1;             nl1 = doc.getElementsByTagName("distance");              Node node1 = nl1.item(nl1.getLength() - 1);             NodeList nl2 = null;             nl2 = node1.getChildNodes();             Node node2 = nl2.item(getNodeIndex(nl2, "value"));             Log.d("DistanceText", node2.getTextContent());             return node2.getTextContent();         } catch (Exception e) {             return "-1";         }          /*          * NodeList nl1; if(doc.getElementsByTagName("distance")!=null){ nl1=          * doc.getElementsByTagName("distance");          *           * Node node1 = nl1.item(nl1.getLength() - 1); NodeList nl2 = null; if          * (node1.getChildNodes() != null) { nl2 = node1.getChildNodes(); Node          * node2 = nl2.item(getNodeIndex(nl2, "value")); Log.d("DistanceText",          * node2.getTextContent()); return node2.getTextContent(); } else return          * "-1";} else return "-1";          */     }      public int getDistanceValue(Document doc) {         try {             NodeList nl1 = doc.getElementsByTagName("distance");             Node node1 = null;             node1 = nl1.item(nl1.getLength() - 1);             NodeList nl2 = node1.getChildNodes();             Node node2 = nl2.item(getNodeIndex(nl2, "value"));             Log.i("DistanceValue", node2.getTextContent());             return Integer.parseInt(node2.getTextContent());         } catch (Exception e) {             return -1;         }         /*          * NodeList nl1 = doc.getElementsByTagName("distance"); Node node1 =          * null; if (nl1.getLength() > 0) node1 = nl1.item(nl1.getLength() - 1);          * if (node1 != null) { NodeList nl2 = node1.getChildNodes(); Node node2          * = nl2.item(getNodeIndex(nl2, "value")); Log.i("DistanceValue",          * node2.getTextContent()); return          * Integer.parseInt(node2.getTextContent()); } else return 0;          */     }      public String getStartAddress(Document doc) {         try {             NodeList nl1 = doc.getElementsByTagName("start_address");             Node node1 = nl1.item(0);             Log.i("StartAddress", node1.getTextContent());             return node1.getTextContent();         } catch (Exception e) {             return "-1";         }      }      public String getEndAddress(Document doc) {         try {             NodeList nl1 = doc.getElementsByTagName("end_address");             Node node1 = nl1.item(0);             Log.i("StartAddress", node1.getTextContent());             return node1.getTextContent();         } catch (Exception e) {             return "-1";             }     }     public String getCopyRights(Document doc) {         try {             NodeList nl1 = doc.getElementsByTagName("copyrights");             Node node1 = nl1.item(0);             Log.i("CopyRights", node1.getTextContent());             return node1.getTextContent();         } catch (Exception e) {         return "-1";         }      }      public ArrayList<LatLng> getDirection(Document doc) {         NodeList nl1, nl2, nl3;         ArrayList<LatLng> listGeopoints = new ArrayList<LatLng>();         nl1 = doc.getElementsByTagName("step");         if (nl1.getLength() > 0) {             for (int i = 0; i < nl1.getLength(); i++) {                 Node node1 = nl1.item(i);                 nl2 = node1.getChildNodes();                  Node locationNode = nl2                         .item(getNodeIndex(nl2, "start_location"));                 nl3 = locationNode.getChildNodes();                 Node latNode = nl3.item(getNodeIndex(nl3, "lat"));                 double lat = Double.parseDouble(latNode.getTextContent());                 Node lngNode = nl3.item(getNodeIndex(nl3, "lng"));                 double lng = Double.parseDouble(lngNode.getTextContent());                 listGeopoints.add(new LatLng(lat, lng));                  locationNode = nl2.item(getNodeIndex(nl2, "polyline"));                 nl3 = locationNode.getChildNodes();                 latNode = nl3.item(getNodeIndex(nl3, "points"));                 ArrayList<LatLng> arr = decodePoly(latNode.getTextContent());                 for (int j = 0; j < arr.size(); j++) {                     listGeopoints.add(new LatLng(arr.get(j).latitude, arr                             .get(j).longitude));                 }                  locationNode = nl2.item(getNodeIndex(nl2, "end_location"));                 nl3 = locationNode.getChildNodes();                 latNode = nl3.item(getNodeIndex(nl3, "lat"));                 lat = Double.parseDouble(latNode.getTextContent());                 lngNode = nl3.item(getNodeIndex(nl3, "lng"));                 lng = Double.parseDouble(lngNode.getTextContent());                 listGeopoints.add(new LatLng(lat, lng));             }         }          return listGeopoints;     }      private int getNodeIndex(NodeList nl, String nodename) {         for (int i = 0; i < nl.getLength(); i++) {             if (nl.item(i).getNodeName().equals(nodename))                 return i;         }         return -1;     }      private ArrayList<LatLng> decodePoly(String encoded) {         ArrayList<LatLng> poly = new ArrayList<LatLng>();         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;              LatLng position = new LatLng((double) lat / 1E5, (double) lng / 1E5);             poly.add(position);         }         return poly;     } } 

Then use this class for your needs.
For example to draw directions:

GMapV2Direction md = new GMapV2Direction(); mMap = ((SupportMapFragment) getSupportFragmentManager()                     .findFragmentById(R.id.map)).getMap(); Document doc = md.getDocument(sourcePosition, destPosition,                     GMapV2Direction.MODE_DRIVING);  ArrayList<LatLng> directionPoint = md.getDirection(doc);             PolylineOptions rectLine = new PolylineOptions().width(3).color(                     Color.RED);              for (int i = 0; i < directionPoint.size(); i++) {                 rectLine.add(directionPoint.get(i));             }             Polyline polylin = mMap.addPolyline(rectLine); 

The sourcePosition, destPosition are from the LatLng type, and you give them the wanted points.

I wrote here parts from my code that I think could help, Any question is welcome.

like image 185
dvrm Avatar answered Oct 19 '22 16:10

dvrm


Using the dvrm solution GMapV2Direction class, it's a good solution and it's still working, but now you need to implement the getDocument method in a new thread to allow network connections. This is an example for an AsyncTask for this method, the rest of the class is the same. You can handle it with a Handle or implement your own interface callback to get the Docmuent xml response.

public class GMapV2DirectionAsyncTask extends AsyncTask<String, Void, Document> {  private final static String TAG = GMapV2DirectionAsyncTask.class.getSimpleName(); private Handler handler; private LatLng  start, end; private String mode;  public GMapV2DirectionAsyncTask(Handler handler, LatLng start, LatLng end, String mode) {     this.start = start;     this.end = end;     this.mode = mode;     this.handler = handler; }  @Override protected Document doInBackground(String... params) {      String url = "http://maps.googleapis.com/maps/api/directions/xml?"             + "origin=" + start.latitude + "," + start.longitude             + "&destination=" + end.latitude + "," + end.longitude             + "&sensor=false&units=metric&mode=" + mode;     Log.d("url", url);     try {         HttpClient httpClient = new DefaultHttpClient();         HttpContext localContext = new BasicHttpContext();         HttpPost httpPost = new HttpPost(url);         HttpResponse response = httpClient.execute(httpPost, localContext);         InputStream in = response.getEntity().getContent();         DocumentBuilder builder = DocumentBuilderFactory.newInstance()                 .newDocumentBuilder();         Document doc = builder.parse(in);         return doc;     } catch (Exception e) {         e.printStackTrace();     }     return null; }  @Override protected void onPostExecute(Document result) {     if (result != null) {         Log.d(TAG, "---- GMapV2DirectionAsyncTask OK ----");         Message message = new Message();         message.obj = result;         handler.dispatchMessage(message);     } else {         Log.d(TAG, "---- GMapV2DirectionAsyncTask ERROR ----");     } }  @Override protected void onPreExecute() { }  @Override protected void onProgressUpdate(Void... values) { } 

}

This is the async handler method for the activity:

    protected void route(LatLng sourcePosition, LatLng destPosition, String mode) {     final Handler handler = new Handler() {         public void handleMessage(Message msg) {             try {                 Document doc = (Document) msg.obj;                 GMapV2Direction md = new GMapV2Direction();                 ArrayList<LatLng> directionPoint = md.getDirection(doc);                 PolylineOptions rectLine = new PolylineOptions().width(15).color(getActivity().getResources().getColor(R.color.magoo_user_base_color));                  for (int i = 0; i < directionPoint.size(); i++) {                     rectLine.add(directionPoint.get(i));                 }                 Polyline polylin = googleMap.addPolyline(rectLine);                 md.getDurationText(doc);             } catch (Exception e) {                 e.printStackTrace();             }         }      };      new GMapV2DirectionAsyncTask(handler, sourcePosition, destPosition, GMapV2Direction.MODE_DRIVING).execute(); } 

One more thing, if the duration value is wrong, solution for it is to change one line of the code of GMapV2Direction class:

Node node1 = nl1.item(nl1.getLength() - 1); 

instead:

Node node1 = nl1.item(0);  
like image 32
Pelanes Avatar answered Oct 19 '22 16:10

Pelanes