1

I would like to draw a path between two points and calculate how much time it will take to move from A to B. I have thought that it is trivial task for Google Maps API.

Everything that I found is small snippet about PolyUtil in documentation and nothing about how to use it.

What I did ?

Inside MapsActivity in onMapReady method I'm trying to create an encoded path:

List<LatLng> latLngList = new ArrayList<>();
latLngList.add(new LatLng(56.952503, 24.083719));
latLngList.add(new LatLng(55.877526, 26.533898));

String encodedPath = PolyUtil.encode(latLngList);

But what is the next ? How to draw this path on map ? How to calculate car/walking distance between this points ?

VLeonovs
  • 2,193
  • 5
  • 24
  • 44

1 Answers1

15

Path is sequence of point . One of the solution is to make HTTP request to Google maps API specifying your two locations as parameters and get back JSON describing the points required to make the path between the two points. Require code to do that are listed below :

  1. Get direction URL require to call Google Maps API
private String  getMapsApiDirectionsUrl(LatLng origin,LatLng dest) {
   // Origin of route
 String str_origin = "origin="+origin.latitude+","+origin.longitude;

 // Destination of route
 String str_dest = "destination="+dest.latitude+","+dest.longitude;        


 // Sensor enabled
 String sensor = "sensor=false";            

 // Building the parameters to the web service
 String parameters = str_origin+"&"+str_dest+"&"+sensor;

 // Output format
 String output = "json";

 // Building the url to the web service
 String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;


 return url;

}
  1. Do the URL call in background

    private class ReadTask extends AsyncTask<String, Void , String> {
    
    @Override
    protected String doInBackground(String... url) {
        // TODO Auto-generated method stub
        String data = "";
        try {
            MapHttpConnection http = new MapHttpConnection();
            data = http.readUr(url[0]);
    
    
        } catch (Exception e) {
            // TODO: handle exception
            Log.d("Background Task", e.toString());
        }
        return data;
    }
    
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        new ParserTask().execute(result);
    }
    
    }
    
  public class MapHttpConnection {
  public String readUr(String mapsApiDirectionsUrl) throws IOException{
      String data = "";
      InputStream istream = null;
      HttpURLConnection urlConnection = null;
      try {
          URL url = new URL(mapsApiDirectionsUrl);
          urlConnection = (HttpURLConnection) url.openConnection();
          urlConnection.connect();
          istream = urlConnection.getInputStream();
          BufferedReader br = new BufferedReader(new InputStreamReader(istream));
          StringBuffer sb = new StringBuffer();
          String line ="";
          while ((line = br.readLine()) != null) {
              sb.append(line);
          }
          data = sb.toString();
          br.close();


      }
      catch (Exception e) {
          Log.d("Exception while reading url", e.toString());
      } finally {
          istream.close();
          urlConnection.disconnect();
      }
      return data;

  }
}
  1. Create Parser class to parse the data from JSON to List of pointes

    public class PathJSONParser {
    
    public List<List<HashMap<String, String>>> parse(JSONObject jObject) {
        List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>();
        JSONArray jRoutes = null;
        JSONArray jLegs = null;
        JSONArray jSteps = null;
        try {
            jRoutes = jObject.getJSONArray("routes");
            for (int i=0 ; i < jRoutes.length() ; i ++) {
                jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
                List<HashMap<String, String>> path = new ArrayList<HashMap<String,String>>();
                for(int j = 0 ; j < jLegs.length() ; j++) {
                    jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps");
                    for(int k = 0 ; k < jSteps.length() ; k ++) {
                        String polyline = "";
                        polyline = (String) ((JSONObject) ((JSONObject) jSteps.get(k)).get("polyline")).get("points");
                        List<LatLng> list = decodePoly(polyline);
                        for(int l = 0 ; l < list.size() ; l ++){
                            HashMap<String, String> hm = new HashMap<String, String>();
                            hm.put("lat",
                                    Double.toString(((LatLng) list.get(l)).latitude));
                            hm.put("lng",
                                    Double.toString(((LatLng) list.get(l)).longitude));
                            path.add(hm);
                        }
                    }
                    routes.add(path);
                }
    
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
        return routes;
    
    }
    
    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;
    }}
    
  2. Do the parse using another Thread to expand performance

private class ParserTask extends AsyncTask<String,Integer, List<List<HashMap<String , String >>>> {
  @Override
  protected List<List<HashMap<String, String>>> doInBackground(
          String... jsonData) {
      // TODO Auto-generated method stub
      JSONObject jObject;
      List<List<HashMap<String, String>>> routes = null;
      try {
          jObject = new JSONObject(jsonData[0]);
          PathJSONParser parser = new PathJSONParser();
          routes = parser.parse(jObject);


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

  @Override
  protected void onPostExecute(List<List<HashMap<String, String>>> routes) {
      ArrayList<LatLng> points = null;
      PolylineOptions polyLineOptions = null;

      // traversing through routes
      for (int i = 0; i < routes.size(); i++) {
          points = new ArrayList<LatLng>();
          polyLineOptions = new PolylineOptions();
          List<HashMap<String, String>> path = routes.get(i);

          for (int j = 0; j < path.size(); j++) {
              HashMap<String, String> point = path.get(j);

              double lat = Double.parseDouble(point.get("lat"));
              double lng = Double.parseDouble(point.get("lng"));
              LatLng position = new LatLng(lat, lng);

              points.add(position);
          }

          polyLineOptions.addAll(points);
          polyLineOptions.width(4);
          polyLineOptions.color(Color.BLUE);
      }

      googleMap.addPolyline(polyLineOptions);

  }}
  1. When you want to get the path of two point
 String url = getMapsApiDirectionsUrl(latlngOne, latlngTwo);                    
    ReadTask downloadTask = new ReadTask();       
    // Start downloading json data from Google Directions API
    downloadTask.execute(url);

To calculate distance between points

float[] results = new float[1];
Location.distanceBetween(latLongA.latitude, latLongB.longitude,
                         latLongB.latitude, latLongB.longitude,
                         results); 

the results will be in meters

Al-Mustafa Azhari
  • 850
  • 1
  • 9
  • 24