Vinay Gaba Vinay Gaba - 4 months ago 40
Android Question

Displaying multiple routes using Directions API in Android

I am using this class to display a route on a map. The problem is that it only displays one route. What I want to do is display multiple alternate routes on the map. Even thought the server response has multiple routes, it only parses the first route and displays it. What changes should I make to display all the routes that the google server returns.Here is my class.

public class GMapV2Direction {
public final static String MODE_DRIVING = "driving";
public final static String MODE = "walking";
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="+MODE+"alternatives=true";

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) {
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();
}

public int getDurationValue (Document doc) {

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());

}

public String getDistanceText (Document doc) {
NodeList nl1 = doc.getElementsByTagName("distance");
Node node1 = nl1.item(0);
NodeList nl2 = node1.getChildNodes();
Node node2 = nl2.item(getNodeIndex(nl2, "text"));
Log.i("DistanceText", node2.getTextContent());
return node2.getTextContent();
}

public int getDistanceValue (Document doc) {
NodeList nl1 = doc.getElementsByTagName("distance");
Node node1 = nl1.item(0);
NodeList nl2 = node1.getChildNodes();
Node node2 = nl2.item(getNodeIndex(nl2, "value"));
Log.i("DistanceValue", node2.getTextContent());
return Integer.parseInt(node2.getTextContent());
}

public String getStartAddress (Document doc) {
NodeList nl1 = doc.getElementsByTagName("start_address");
Node node1 = nl1.item(0);
Log.i("StartAddress", node1.getTextContent());
return node1.getTextContent();
}

public String getEndAddress (Document doc) {
NodeList nl1 = doc.getElementsByTagName("end_address");
Node node1 = nl1.item(0);
Log.i("EndAddress", node1.getTextContent());
return node1.getTextContent();
}

public String getCopyRights (Document doc) {
NodeList nl1 = doc.getElementsByTagName("copyrights");
Node node1 = nl1.item(0);
Log.i("CopyRights", node1.getTextContent());
return node1.getTextContent();
}

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

Answer

i think you don't have to get the response of Google Server and parse it in Document, other wise you can convert from InputStream to String using:

private String convertStreamToString(final InputStream input) throws Exception {
    try {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        final StringBuffer sBuf = new StringBuffer();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sBuf.append(line);
        }
        return sBuf.toString();
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            input.close();
        } catch (Exception e) {
            throw e;
        }
    }

then you will have to parse the response as JSONObject

JSONObject jSONObject = new JSONObject(string);

then you get JSONArray named routes

JSONArray routeJSONArray = jSONObject.getJSONArray("routes");

now you can start fetching data from each route by getting its index from JSONArray.

i have written a snippet of code as a model of route

Route.java

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;

import com.google.android.gms.maps.model.Polyline;

public class Route implements Serializable {

    private static final long serialVersionUID = 1L;
    private Bound bounds;
    private String copyrights;
    private List<Leg> legs;
    private Polyline overviewPolyLine;
    private String summary;

    public Route(Context context) {
        legs = new ArrayList<Leg>();
    }

    public Bound getBounds() {
        return bounds;
    }

    public void setBounds(Bound bounds) {
        this.bounds = bounds;
    }

    public String getCopyrights() {
        return copyrights;
    }

    public void setCopyrights(String copyrights) {
        this.copyrights = copyrights;
    }

    public List<Leg> getLegs() {
        return legs;
    }

    public void setLegs(List<Leg> legs) {
        this.legs = legs;
    }

    public void addLeg(Leg leg) {
        this.legs.add(leg);
    }

    public Polyline getOverviewPolyLine() {
        return overviewPolyLine;
    }

    public void setOverviewPolyLine(Polyline overviewPolyLine) {
        this.overviewPolyLine = overviewPolyLine;
    }

    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

}

Bound.java

import com.google.android.gms.maps.model.LatLng;

public class Bound {
    private LatLng northEast;
    private LatLng southWest;
    public LatLng getNorthEast() {
        return northEast;
    }
    public void setNorthEast(LatLng northEast) {
        this.northEast = northEast;
    }
    public LatLng getSouthWest() {
        return southWest;
    }
    public void setSouthWest(LatLng southWest) {
        this.southWest = southWest;
    }
}

Leg.java

import java.util.ArrayList;
import java.util.List;

import com.google.android.gms.maps.model.LatLng;

public class Leg {
    private Distance distance;
    private Duration duration;
    private String endAddress;
    private LatLng endLocation;
    private String startAddress;
    private LatLng startLocation;
    private List<Step> steps;

    public Leg() {
        steps = new ArrayList<Step>();
    }

    public Distance getDistance() {
        return distance;
    }

    public void setDistance(Distance distance) {
        this.distance = distance;
    }

    public Duration getDuration() {
        return duration;
    }

    public void setDuration(Duration duration) {
        this.duration = duration;
    }

    public String getEndAddress() {
        return endAddress;
    }

    public void setEndAddress(String endAddress) {
        this.endAddress = endAddress;
    }

    public LatLng getEndLocation() {
        return endLocation;
    }

    public void setEndLocation(LatLng endLocation) {
        this.endLocation = endLocation;
    }

    public String getStartAddress() {
        return startAddress;
    }

    public void setStartAddress(String startAddress) {
        this.startAddress = startAddress;
    }

    public LatLng getStartLocation() {
        return startLocation;
    }

    public void setStartLocation(LatLng startLocation) {
        this.startLocation = startLocation;
    }

    public List<Step> getSteps() {
        return steps;
    }

    public void setSteps(List<Step> steps) {
        this.steps = steps;
    }

    public void addStep(Step step) {
        this.steps.add(step);
    }

}

Distance.java

public class Distance {
    private String text;
    private long value;

    public Distance(String text, long value) {
        this.text = text;
        this.value = value;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }

}

Duration.java

public class Duration {
    public Duration(String text, long value) {
        this.text = text;
        this.value = value;
    }

    private String text;
    private long value;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }

}

Step.java

import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;

import com.google.android.gms.maps.model.LatLng;
import com.nweave.etaxi.driver.R;

public class Step {
    private Distance distance;
    private Duration duration;
    private LatLng endLocation;
    private LatLng startLocation;
    private String htmlInstructions;
    private String travelMode;
    private List<LatLng> points;

    public List<LatLng> getPoints() {
        return points;
    }

    public void setPoints(List<LatLng> points) {
        this.points = points;
    }

    public Distance getDistance() {
        return distance;
    }

    public void setDistance(Distance distance) {
        this.distance = distance;
    }

    public Duration getDuration() {
        return duration;
    }

    public void setDuration(Duration duration) {
        this.duration = duration;
    }

    public LatLng getEndLocation() {
        return endLocation;
    }

    public void setEndLocation(LatLng endLocation) {
        this.endLocation = endLocation;
    }

    public LatLng getStartLocation() {
        return startLocation;
    }

    public void setStartLocation(LatLng startLocation) {
        this.startLocation = startLocation;
    }

    public String getHtmlInstructions() {
        return htmlInstructions;
    }

    public void setHtmlInstructions(String htmlInstructions) {
        this.htmlInstructions = htmlInstructions;
    }

    public String getTravelMode() {
        return travelMode;
    }

    public void setTravelMode(String travelMode) {
        this.travelMode = travelMode;
    }
}

the parsing function will be

public List<Route> parse(String routesJSONString) throws Exception {
    try {
        List<Route> routeList = new ArrayList<Route>();
        final JSONObject jSONObject = new JSONObject(routesJSONString);
        JSONArray routeJSONArray = jSONObject.getJSONArray(ROUTES);
        Route route;
        JSONObject routesJSONObject;
        for (int m = 0; m < routeJSONArray.length(); m++) {
            route = new Route(context);
            routesJSONObject = routeJSONArray.getJSONObject(m);
            JSONArray legsJSONArray;
            route.setSummary(routesJSONObject.getString(SUMMARY));
            legsJSONArray = routesJSONObject.getJSONArray(LEGS);
            JSONObject legJSONObject;
            Leg leg;
            JSONArray stepsJSONArray;
            for (int b = 0; b < legsJSONArray.length(); b++) {
                leg = new Leg();
                legJSONObject = legsJSONArray.getJSONObject(b);
                leg.setDistance(new Distance(legJSONObject.optJSONObject(DISTANCE).optString(TEXT), legJSONObject.optJSONObject(DISTANCE).optLong(VALUE)));
                leg.setDuration(new Duration(legJSONObject.optJSONObject(DURATION).optString(TEXT), legJSONObject.optJSONObject(DURATION).optLong(VALUE)));
                stepsJSONArray = legJSONObject.getJSONArray(STEPS);
                JSONObject stepJSONObject, stepDurationJSONObject, legPolyLineJSONObject, stepStartLocationJSONObject, stepEndLocationJSONObject;
                Step step;
                String encodedString;
                LatLng stepStartLocationLatLng, stepEndLocationLatLng;
                for (int i = 0; i < stepsJSONArray.length(); i++) {
                    stepJSONObject = stepsJSONArray.getJSONObject(i);
                    step = new Step();
                    JSONObject stepDistanceJSONObject = stepJSONObject.getJSONObject(DISTANCE);
                    step.setDistance(new Distance(stepDistanceJSONObject.getString(TEXT), stepDistanceJSONObject.getLong(VALUE)));
                    stepDurationJSONObject = stepJSONObject.getJSONObject(DURATION);
                    step.setDuration(new Duration(stepDurationJSONObject.getString(TEXT), stepDurationJSONObject.getLong(VALUE)));
                    stepEndLocationJSONObject = stepJSONObject.getJSONObject(END_LOCATION);
                    stepEndLocationLatLng = new LatLng(stepEndLocationJSONObject.getDouble(LATITUDE), stepEndLocationJSONObject.getDouble(LONGITUDE));
                    step.setEndLocation(stepEndLocationLatLng);
                    step.setHtmlInstructions(stepJSONObject.getString(HTML_INSTRUCTION));
                    legPolyLineJSONObject = stepJSONObject.getJSONObject(POLYLINE);
                    encodedString = legPolyLineJSONObject.getString(POINTS);
                    step.setPoints(decodePolyLines(encodedString));
                    stepStartLocationJSONObject = stepJSONObject.getJSONObject(START_LOCATION);
                    stepStartLocationLatLng = new LatLng(stepStartLocationJSONObject.getDouble(LATITUDE), stepStartLocationJSONObject.getDouble(LONGITUDE));
                    step.setStartLocation(stepStartLocationLatLng);
                    leg.addStep(step);
                }
                route.addLeg(leg);
            }
            routeList.add(route);
        }
        return routeList;
    } catch (Exception e) {
        throw e;
    }

Regarding the Step Image there is an HTML instruction and another field called maneuver where according to this field you will choose your image

i hope this helps ;)