Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
260 views
in Technique[技术] by (71.8m points)

android - Draw driving route between 2 GeoPoints on GoogleMap SupportMapFragment

This is a tricky question, been banging my head for a day, please help.

I use Google Maps Apis to get the shortest driving distance and its routes, points, etc between 2 GeoPoints that I provide, see code below

private JSONObject GetDistance(String src, String dest) throws Exception
{
    StringBuilder urlString = new StringBuilder();
    urlString.append("http://maps.googleapis.com/maps/api/directions/json?");
    urlString.append("origin=");// from
    urlString.append(src);
    urlString.append("&destination=");// to
    urlString.append(dest);
    urlString.append("&mode=driving&sensor=true&units=imperial");

    // get the JSON And parse it to get the directions data.
    HttpURLConnection urlConnection = null;
    URL url = null;

    url = new URL(urlString.toString());
    urlConnection = (HttpURLConnection) url.openConnection();
    urlConnection.setRequestMethod("GET");
    urlConnection.setDoOutput(true);
    urlConnection.setDoInput(true);
    urlConnection.connect();

    InputStream inStream = urlConnection.getInputStream();
    BufferedReader bReader = new BufferedReader(new InputStreamReader(inStream));

    String temp, response = "";
    while ((temp = bReader.readLine()) != null)
    {
        // Parse data
        response += temp;
    }
    // Close the reader, stream & connection
    bReader.close();
    inStream.close();
    urlConnection.disconnect();

    JSONObject object = (JSONObject) new JSONTokener(response).nextValue();

    return (object);
}

I also plot the 2 GeoPoints on a google maps fragment, I use SupportMapFragment, i.e. this library com.google.android.gms.maps.SupportMapFragment

what I want to do is, I want to draw the route that I get from the getDistance function above, it outputs the data in JSON which I can easily handle.

Here is the JSON object that I get from the getDistance function
{
    "status": "OK",
    "routes": [
        {
            "waypoint_order": [],
            "summary": "Wilbraham Rd/A6010",
            "bounds": {
                "southwest": {
                    "lng": -2.26773,
                    "lat": 53.4301
                },
                "northeast": {
                    "lng": -2.19414,
                    "lat": 53.45106000000001
                }
            },
            "legs": [
                {
                    "duration": {
                        "value": 797,
                        "text": "13 mins"
                    },
                    "distance": {
                        "value": 7289,
                        "text": "4.5 mi"
                    },
                    "end_location": {
                        "lng": -2.19414,
                        "lat": 53.43052
                    },
                    "start_address": "137 College Road, Manchester, Greater Manchester M16 0AA, UK",
                    "end_address": "6 Ealing Place, Manchester M19, UK",
                    "start_location": {
                        "lng": -2.26773,
                        "lat": 53.45106000000001
                    },
                    "via_waypoint": [],
                    "steps": [
                        {
                            "html_instructions": "Head <b>southeast</b> on <b>College Rd</b> toward <b>Park Dr</b>",
                            "duration": {
                                "value": 83,
                                "text": "1 min"
                            },
                            "distance": {
                                "value": 729,
                                "text": "0.5 mi"
                            },
                            "end_location": {
                                "lng": -2.25758,
                                "lat": 53.45005
                            },
                            "polyline": {
                                "points": "ctfeIh|yLrBaEdAoB`@w@N]BKDM@Q@M?]?WC}AAgAGyG?mAI{GG{JM_HAo@"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.26773,
                                "lat": 53.45106000000001
                            }
                        },
                        {
                            "html_instructions": "Turn <b>right</b> onto <b>Withington Rd</b>",
                            "duration": {
                                "value": 96,
                                "text": "2 mins"
                            },
                            "distance": {
                                "value": 747,
                                "text": "0.5 mi"
                            },
                            "end_location": {
                                "lng": -2.25703,
                                "lat": 53.44339
                            },
                            "polyline": {
                                "points": "ymfeIz|wLJ@v@TL@N?H?HAHCJEXKhAy@JGTEH?|BAzAExAAN?z@Cb@?dA?d@AdFKxCGfCC"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.25758,
                                "lat": 53.45005
                            }
                        },
                        {
                            "html_instructions": "Turn <b>left</b> onto <b>Wilbraham Rd/A6010</b>",
                            "duration": {
                                "value": 249,
                                "text": "4 mins"
                            },
                            "distance": {
                                "value": 2565,
                                "text": "1.6 mi"
                            },
                            "end_location": {
                                "lng": -2.21852,
                                "lat": 53.44261
                            },
                            "polyline": {
                                "points": "edeeIlywLAsGAgA@}D@m@@{EFqGHcG?]LmGHaFDyD@gB?sC?oDIw@?i@AuACoCKiGWcNe@mQKcEK}DASAe@C{AAcAAq@?_B?mABkALkCFgBF[LsCp@sQFyADmALkDj@wNx@_U@wA"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.25703,
                                "lat": 53.44339
                            }
                        },
                        {
                            "html_instructions": "Continue straight onto <b>Moseley Rd/B5093</b><div style="font-size:0.9em">Continue to follow Moseley Rd</div><div style="font-size:0.9em">Go through 1 roundabout</div>",
                            "duration": {
                                "value": 100,
                                "text": "2 mins"
                            },
                            "distance": {
                                "value": 974,
                                "text": "0.6 mi"
                            },
                            "end_location": {
                                "lng": -2.20411,
                                "lat": 53.44213000000001
                            },
                            "polyline": {
                                "points": "i_eeIvhpLDsA@a@Ba@D{@JgAPsAVgBHi@De@Fe@Bc@Bk@D{@@_A?qAB}I?gA@oDBmJ@qD?g@@gGBgD@[?Q?MA[AUG]A??AA??AA??AA??A?AA??A?A?AAA?A?A?A?A?A?A?A@??A?A?A@A?A@??A@A@A@?@AYiE"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.21852,
                                "lat": 53.44261
                            }
                        },
                        {
                            "html_instructions": "At the roundabout, take the <b>2nd</b> exit onto <b>Kingsway/A34</b>",
                            "duration": {
                                "value": 63,
                                "text": "1 min"
                            },
                            "distance": {
                                "value": 694,
                                "text": "0.4 mi"
                            },
                            "end_location": {
                                "lng": -2.20629,
                                "lat": 53.43661
                            },
                            "polyline": {
                                "points": "i|deItnmLC?AAA?AAAAA?AA?AACAAAAAC?AAC?AAC?C?C?CAA?C?C@C?C?A?C@C?C@A?C@A@C?A@A@A@A@A@A@?@A@?@A@?@?B?@@@?@@@?@@@??@@@@@?@@@@@?@@@?@?@@@b@V^VZHDBHBf@Rv@ZLD`@NJDB@h@RrFvBLDhGxBjFdB"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.20411,
                                "lat": 53.44213000000001
                            }
                        },
                        {
                            "html_instructions": "Turn <b>left</b> onto <b>Grangethorpe Dr</b>",
                            "duration": {
                                "value": 56,
                                "text": "1 min"
                            },
                            "distance": {
                                "value": 415,
                                "text": "0.3 mi"
                            },
                            "end_location": {
                                "lng": -2.20015,
                                "lat": 53.43616
                            },
                            "polyline": {
                                "points": "yyceIh|mL\aCBUBa@RcCFc@FcAHiB@MReRM}@AI"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.20629,
                                "lat": 53.43661
                            }
                        },
                        {
                            "html_instructions": "Continue onto <b>Crossley Rd</b>",
                            "duration": {
                                "value": 45,
                                "text": "1 min"
                            },
                            "distance": {
                                "value": 394,
                                "text": "0.2 mi"
                            },
                            "end_location": {
                                "lng": -2.19433,
                                "lat": 53.43562000000001
                            },
                            "polyline": {
                                "points": "_wceI|ulLGyCBY@GJs@L}@BaA?GFqCBiBDkB@CLkBPkBRsCF{@"
                            },
                            "travel_mode": "DRIVING",
                            "start_location": {
                                "lng": -2.20015,
                                "lat": 53.43616
                            }
                        },
                        {
                            "html_instructions": "Turn <b>right</b> onto <b>Errwood Rd</b>",
                            "duration": {
                                "value": 60,
                                "text": "1 min"
                            },
                            "distance": {
                                "value": 607,

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Take a look at this code I was provided here in one of the posts for creating Polyline from Google Direction API, you can change the class that gets the data if you want to get it from other source but this is how you do it. Create a class that will be responsible for getting the direction and parsing:

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="+ mode;

    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("StartAddress", 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;
}
}

Create a getDirections AsyncTask:

public class GetDirectionsAsyncTask extends AsyncTask<Map<String, String>, Object, ArrayList<LatLng>> {

public static final String USER_CURRENT_LAT = "user_current_lat";
public static final String USER_CURRENT_LONG = "user_current_long";
public static final String DESTINATION_LAT = "destination_lat";
public static final String DESTINATION_LONG = "destination_long";
public static final String DIRECTIONS_MODE = "directions_mode";
private MapFragmentActivity activity;
private String url;

private Exception exception;

private Dialog progressDialog;

public GetDirectionsAsyncTask(MapFragmentActivity activity /*String url*/) 
{
    super();
    this.activity = activity;

    //  this.url = url;
}

public void onPreExecute() {
    progressDialog = DialogUtils.createProgressDialog(activity, activity.getString(R.string.get_data_dialog_message));
    progressDialog.show();
}

@Override
public void onPostExecute(ArrayList<LatLng> result) {
    progressDialog.dismiss();

    if (exception == null) {
        activity.handleGetDirectionsResult(result);
    } else {
        processException();
    }
}

@Override
protected ArrayList<LatLng> doInBackground(Map<String, String>... params) {

    Map<String, String> paramMap = params[0];
    try{
        LatLng fromPosition = new LatLng(Double.valueOf(paramMap.get(USER_CURRENT_LAT)) , Double.valueOf(paramMap.get(USER_CURRENT_LONG)));
        LatLng toPosition = new LatLng(Double.valueOf(paramMap.get(DESTINATION_LAT)) , Double.valueOf(paramMap.get(DESTINATION_LONG)));
        GMapV2Direction md = new GMapV2Direction();
        Document doc = md.getDocument(fromPosition, toPosition, paramMap.get(DIRECTIONS_MODE));
        ArrayList<LatLng> directionPoints = md.getDirection(doc);
        return directionPoints;

    }
    catch (Exception e) {
        exception = e;
        return null;
    }
}

private void processException() {
    Toast.makeText(activity, activity.getString(R.string.error_when_retrieving_data), 3000).show();
}

}

In your Activity create those 2 methods:

public void handleGetDirectionsResult(ArrayList<LatLng> directionPoints)
{
    Polyline newPolyline;
    GoogleMap mMap = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); 
    PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.RED);

    for(int i = 0 ; i < directionPoints.size() ; i++) 
    {          
        rectLine.add(directionPoints.get(i));
    }
    newPolyline = mMap.addPolyline(rectLine);
}


public void findDirections(double fromPositionDoubleLat, double fromPositionDoubleLong, double toPositionDoubleLat, double toPositionDoubleLong, String mode)
{
    Map<String, String> map = new HashMap<String, String>();
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LAT, String.valueOf(fromPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LONG, String.valueOf(fromPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DESTINATION_LAT, String.valueOf(toPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.DESTINATION_LONG, String.valueOf(toPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DIRECTIONS_MODE, mode);

    GetDirectionsAsyncTask asyncTask = new GetDirectionsAsyncTask(this);
    asyncTask.execute(map); 
}

Finally run this method to create the Polyline:

findDirections(AppObj.getInstance().currentUserLocation.getLatitude(),
                                                   AppObj.getInstance().currentUserLocation.getLongitude(),
                                                   clickMarkerLatLng.latitude, clickMarkerLatLng.longitude, GMapV2Direction.MODE_DRIVING );

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...