Draw path between two points using Google Maps And

2018-12-31 15:14发布

问题:

Google changed its map API for Android and introduced API V2. The previous codes for drawing path are not working with API V2.

I have managed to draw a path with API V2. I had searched a lot for the solution but did not find any answer. So I am sharing its answer.

回答1:

First of all we will get source and destination points between which we have to draw route. Then we will pass these attribute to below function.

 public String makeURL (double sourcelat, double sourcelog, double destlat, double destlog ){
        StringBuilder urlString = new StringBuilder();
        urlString.append(\"http://maps.googleapis.com/maps/api/directions/json\");
        urlString.append(\"?origin=\");// from
        urlString.append(Double.toString(sourcelat));
        urlString.append(\",\");
        urlString.append(Double.toString( sourcelog));
        urlString.append(\"&destination=\");// to
        urlString.append(Double.toString( destlat));
        urlString.append(\",\");
        urlString.append(Double.toString( destlog));
        urlString.append(\"&sensor=false&mode=driving&alternatives=true\");
        urlString.append(\"&key=YOUR_API_KEY\");
        return urlString.toString();
 }

This function will make the url that we will send to get Direction API response. Then we will parse that response . The parser class is

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = \"\";
    // constructor
    public JSONParser() {
    }
    public String getJSONFromUrl(String url) {

        // Making HTTP request
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();           

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, \"iso-8859-1\"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + \"\\n\");
            }

            json = sb.toString();
            is.close();
        } catch (Exception e) {
            Log.e(\"Buffer Error\", \"Error converting result \" + e.toString());
        }
        return json;

    }
}

This parser will return us string. We will call it like that.

JSONParser jParser = new JSONParser();
String json = jParser.getJSONFromUrl(url);

Now we will send this string to our drawpath function. The drawpath function is

public void drawPath(String  result) {

    try {
            //Tranform the string into a json object
           final JSONObject json = new JSONObject(result);
           JSONArray routeArray = json.getJSONArray(\"routes\");
           JSONObject routes = routeArray.getJSONObject(0);
           JSONObject overviewPolylines = routes.getJSONObject(\"overview_polyline\");
           String encodedString = overviewPolylines.getString(\"points\");
           List<LatLng> list = decodePoly(encodedString);
           Polyline line = mMap.addPolyline(new PolylineOptions()
                                    .addAll(list)
                                    .width(12)
                                    .color(Color.parseColor(\"#05b1fb\"))//Google maps blue color
                                    .geodesic(true)
                    );
           /*
           for(int z = 0; z<list.size()-1;z++){
                LatLng src= list.get(z);
                LatLng dest= list.get(z+1);
                Polyline line = mMap.addPolyline(new PolylineOptions()
                .add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude,   dest.longitude))
                .width(2)
                .color(Color.BLUE).geodesic(true));
            }
           */
    } 
    catch (JSONException e) {

    }
} 

Above code will draw the path on mMap. The code of decodePoly is

private List<LatLng> decodePoly(String encoded) {

    List<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 p = new LatLng( (((double) lat / 1E5)),
                 (((double) lng / 1E5) ));
        poly.add(p);
    }

    return poly;
}

As direction call may take time so we will do all this in Asynchronous task. My Asynchronous task was

private class connectAsyncTask extends AsyncTask<Void, Void, String>{
    private ProgressDialog progressDialog;
    String url;
    connectAsyncTask(String urlPass){
        url = urlPass;
    }
    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage(\"Fetching route, Please wait...\");
        progressDialog.setIndeterminate(true);
        progressDialog.show();
    }
    @Override
    protected String doInBackground(Void... params) {
        JSONParser jParser = new JSONParser();
        String json = jParser.getJSONFromUrl(url);
        return json;
    }
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);   
        progressDialog.hide();        
        if(result!=null){
            drawPath(result);
        }
    }
}

I hope it will help.



回答2:

Dont know whether I should put this as answer or not...

I used @Zeeshan0026\'s solution to draw the path...and the problem was that if I draw path once, and then I do try to draw path once again, both two paths show and this continues...paths showing even when markers were deleted... while, ideally, old paths\' shouldn\'t be there once new path is drawn / markers are deleted..

going through some other question over SO, I had the following solution

I add the following function in Zeeshan\'s class

 public void clearRoute(){

         for(Polyline line1 : polylines)
         {
             line1.remove();
         }

         polylines.clear();

     }

in my map activity, before drawing the path, I called this function.. example usage as per my app is

private Route rt;

rt.clearRoute();

            if (src == null) {
                Toast.makeText(getApplicationContext(), \"Please select your Source\", Toast.LENGTH_LONG).show();
            }else if (Destination == null) {
                Toast.makeText(getApplicationContext(), \"Please select your Destination\", Toast.LENGTH_LONG).show();
            }else if (src.equals(Destination)) {
                Toast.makeText(getApplicationContext(), \"Source and Destinatin can not be the same..\", Toast.LENGTH_LONG).show();
            }else{

                rt.drawRoute(mMap, MapsMainActivity.this, src,
                        Destination, false, \"en\");
            }

you can use rt.clearRoute(); as per your requirements.. Hoping that it will save a few minutes of someone else and will help some beginner in solving this issue..

Complete Class Code

see on github

Edit: here is part of code from mainactivity..

case R.id.mkrbtn_set_dest:
                    Destination = selmarker.getPosition();
                    destmarker = selmarker;
                    desShape = createRouteCircle(Destination, false);

                    if (src == null) {
                        Toast.makeText(getApplicationContext(),
                                \"Please select your Source first...\",
                                Toast.LENGTH_LONG).show();
                    } else if (src.equals(Destination)) {
                        Toast.makeText(getApplicationContext(),
                                \"Source and Destinatin can not be the same..\",
                                Toast.LENGTH_LONG).show();
                    } else {

                        if (isNetworkAvailable()) {
                            rt.drawRoute(mMap, MapsMainActivity.this, src,
                                    Destination, false, \"en\");
                            src = null;
                            Destination = null;

                        } else {
                            Toast.makeText(
                                    getApplicationContext(),
                                    \"Internet Connection seems to be OFFLINE...!\",
                                    Toast.LENGTH_LONG).show();

                        }

                    }

                    break;

Edit 2 as per comments

usage :

//variables as data members
GoogleMap mMap;
private Route rt;
static LatLng src;
static LatLng Destination;
//MapsMainActivity is my activity
//false for interim stops for traffic, google
// en language for html description returned

rt.drawRoute(mMap, MapsMainActivity.this, src,
                            Destination, false, \"en\");


回答3:

in below code midpointsList is an ArrayList of waypoints

private String getMapsApiDirectionsUrl(GoogleMap googleMap, LatLng startLatLng, LatLng endLatLng, ArrayList<LatLng> midpointsList) {
    String origin = \"origin=\" + startLatLng.latitude + \",\" + startLatLng.longitude;

    String midpoints = \"\";
    for (int mid = 0; mid < midpointsList.size(); mid++) {
        midpoints += \"|\" + midpointsList.get(mid).latitude + \",\" + midpointsList.get(mid).longitude;
    }

    String waypoints = \"waypoints=optimize:true\" + midpoints + \"|\";

    String destination = \"destination=\" + endLatLng.latitude + \",\" + endLatLng.longitude;
    String key = \"key=AIzaSyCV1sOa_7vASRBs6S3S6t1KofFvDhjohvI\";

    String sensor = \"sensor=false\";
    String params = origin + \"&\" + waypoints + \"&\" + destination + \"&\" + sensor + \"&\" + key;
    String output = \"json\";
    String url = \"https://maps.googleapis.com/maps/api/directions/\" + output + \"?\" + params;


    Log.e(\"url\", url);
    parseDirectionApidata(url, googleMap);
    return url;
}

Then copy and paste this url in your browser to check And the below code is to parse the url

    private void parseDirectionApidata(String url, final GoogleMap googleMap) {

    final JSONObject jsonObject = new JSONObject();

    try {

        AppUtill.getJsonWithHTTPPost(ViewMapActivity.this, 1, new ServiceCallBack() {
            @Override
            public void serviceCallBack(int id, JSONObject jsonResult) throws JSONException {

                if (jsonResult != null) {

                    Log.e(\"jsonRes\", jsonResult.toString());

                    String status = jsonResult.optString(\"status\");

                    if (status.equalsIgnoreCase(\"ok\")) {
                        drawPath(jsonResult, googleMap);
                    }

                } else {

                    Toast.makeText(ViewMapActivity.this, \"Unable to parse Directions Data\", Toast.LENGTH_LONG).show();
                }

            }
        }, url, jsonObject);

    } catch (Exception e) {
        e.printStackTrace();

    }
}

And then pass the result to the drawPath method

    public void drawPath(JSONObject jObject, GoogleMap googleMap) {

    List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
    JSONArray jRoutes = null;
    JSONArray jLegs = null;
    JSONArray jSteps = null;
    List<LatLng> list = null;
    try {

        Toast.makeText(ViewMapActivity.this, \"Drawing Path...\", Toast.LENGTH_SHORT).show();
        jRoutes = jObject.getJSONArray(\"routes\");

        /** Traversing all routes */
        for (int i = 0; i < jRoutes.length(); i++) {
            jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray(\"legs\");
            List path = new ArrayList<HashMap<String, String>>();

            /** Traversing all legs */
            for (int j = 0; j < jLegs.length(); j++) {
                jSteps = ((JSONObject) jLegs.get(j)).getJSONArray(\"steps\");

                /** Traversing all steps */
                for (int k = 0; k < jSteps.length(); k++) {
                    String polyline = \"\";
                    polyline = (String) ((JSONObject) ((JSONObject) jSteps.get(k)).get(\"polyline\")).get(\"points\");
                    list = decodePoly(polyline);
                }
                Log.e(\"list\", list.toString());
                routes.add(path);
                Log.e(\"routes\", routes.toString());
                if (list != null) {
                    Polyline line = googleMap.addPolyline(new PolylineOptions()
                            .addAll(list)
                            .width(12)
                            .color(Color.parseColor(\"#FF0000\"))//Google maps blue color #05b1fb
                            .geodesic(true)
                    );
                }
            }
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

}

  private List<LatLng> decodePoly(String encoded) {

    List<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 p = new LatLng((((double) lat / 1E5)),
                (((double) lng / 1E5)));
        poly.add(p);
    }

    return poly;
}

decode poly function is to decode the points(lat and long) provided by Directions API in encoded form