19

i want to draw a road direction in android like the below image. i tried using polyline but this plots a straight lines betweens two LatLngs. How can i achieve this as same as the google map. thanks in advance.enter image description here

j0k
  • 22,600
  • 28
  • 79
  • 90
Amarnath
  • 1,091
  • 3
  • 19
  • 32

2 Answers2

38

Create one Class called "DirectionsJSONParser "

public class DirectionsJSONParser {


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 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 (JSONException e) {
        e.printStackTrace();
    }catch (Exception e){
    }
    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;
}}

In Main Activity

public class MainActivity extends FragmentActivity {

GoogleMap map;
ArrayList<LatLng> markerPoints;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initializing array List
    markerPoints = new ArrayList<LatLng>();

    // Getting reference to SupportMapFragment of the activity_main
    SupportMapFragment fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);

    // Getting Map for the SupportMapFragment
    map = fm.getMap();

    map.setMyLocationEnabled(true);

    map.setOnMapClickListener(new OnMapClickListener() {

        @Override
        public void onMapClick(LatLng point) {

            if(markerPoints.size()>1){
                markerPoints.clear();
                map.clear();
            }

            markerPoints.add(point);

            MarkerOptions options = new MarkerOptions();

            options.position(point);

             if(markerPoints.size()==1){
                   options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            }else if(markerPoints.size()==2){
                options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
            }

            map.addMarker(options);

            if(markerPoints.size() >= 2){
                LatLng origin = markerPoints.get(0);
                LatLng dest = markerPoints.get(1);

                String url = getDirectionsUrl(origin, dest);

                DownloadTask downloadTask = new DownloadTask();

                downloadTask.execute(url);
            }
        }
    });
}

private String getDirectionsUrl(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";

    String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;

    return url;
}

private String downloadUrl(String strUrl) throws IOException{
    String data = "";
    InputStream iStream = null;
    HttpURLConnection urlConnection = null;
    try{
        URL url = new URL(strUrl);

        urlConnection = (HttpURLConnection) url.openConnection();

        // Connecting to url
        urlConnection.connect();

        // Reading data from url
        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 downloading url", e.toString());
    }finally{
        iStream.close();
        urlConnection.disconnect();
    }
    return data;
}

// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String>{

    // Downloading data in non-ui thread
    @Override
    protected String doInBackground(String... url) {

        // For storing data from web service
        String data = "";

        try{
            // Fetching the data from web service
            data = downloadUrl(url[0]);
        }catch(Exception e){
            Log.d("Background Task",e.toString());
        }
        return data;
    }

    // Executes in UI thread, after the execution of
    // doInBackground()
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        ParserTask parserTask = new ParserTask();

        // Invokes the thread for parsing the JSON data
        parserTask.execute(result);
    }
}


private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> {

    @Override
    protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {

        JSONObject jObject;
        List<List<HashMap<String, String>>> routes = null;

        try{
            jObject = new JSONObject(jsonData[0]);
            DirectionsJSONParser parser = new DirectionsJSONParser();

            // Starts parsing data
            routes = parser.parse(jObject);
        }catch(Exception e){
            e.printStackTrace();
        }
        return routes;
    }

    @Override
    protected void onPostExecute(List<List<HashMap<String, String>>> result) {
        ArrayList<LatLng> points = null;
        PolylineOptions lineOptions = null;
        MarkerOptions markerOptions = new MarkerOptions();

        // Traversing through all the routes
        for(int i=0;i<result.size();i++){
            points = new ArrayList<LatLng>();
            lineOptions = new PolylineOptions();

            // Fetching i-th route
            List<HashMap<String, String>> path = result.get(i);

            // Fetching all the points in i-th route
            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);
            }

            // Adding all the points in the route to LineOptions
            lineOptions.addAll(points);
            lineOptions.width(2);
            lineOptions.color(Color.RED);
        }

        // Drawing polyline in the Google Map for the i-th route
        map.addPolyline(lineOptions);
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}}
Dhruv
  • 1,862
  • 3
  • 20
  • 38
  • 1
    works perfect. You should create some tutorial on a website :) +1 – alicanbatur Sep 26 '13 at 14:46
  • 1
    thanks for suggestion @alicanbatur. I have already a blog.[http://dhruvvaishnav.blogspot.in/] – Dhruv Nov 21 '13 at 09:00
  • @DhruvVaishnav Thanks it's works fine; How can I remove Line when I want to draw another path ? – Amir Aug 15 '15 at 09:29
  • @DhruvVaishnav can you explain a code a little bit? I have my own custom LatLng points and am trying to understand how to integrate your code into my own code – zooter Apr 22 '16 at 09:37
  • Perfect Answer ...!! – iDeveloper Jan 21 '17 at 12:52
  • im using your method and I'm getting OOM from adding to many polylines, I'm trying to travel across all lower 48 states. any advice on how to cut down memory usage with this approach? – JRowan Feb 27 '18 at 00:41
13

You can use this function to show direction in preinstalled Google NavigationApp

 public void showDirections(double lat, double lng, double lat1, double lng1) {

        final Intent intent = new
                Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?" +
                "saddr=" + lat + "," + lng + "&daddr=" + lat1 + "," +
                lng1));
        intent.setClassName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity");
        startActivity(intent);

    }
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
RaviPatidar
  • 1,438
  • 1
  • 18
  • 29