Highlight a specified route on Google Maps v2 Android
Asked Answered
J

3

8

Right, so I'm currently using the Google Directions API in my app to retrieve the route between two locations.

When I send a request for a route directions, I retrieve a number of details in JSON regarding the route including the names of every road along the route, their corresponding start and end lat-long co-ordinates, and their polyline value.

For example: If I send the request http://maps.googleapis.com/maps/api/directions/json?origin=redfern+ave,+dublin&destination=limetree+ave,+dublin&sensor=false between two roads, I get the following JSON response (output for one road along route).

 {
                     "distance" : {
                        "text" : "0.2 km",
                        "value" : 203
                     },
                     "duration" : {
                        "text" : "1 min",
                        "value" : 18
                     },
                     "end_location" : {
                        "lat" : 53.435250,
                        "lng" : -6.132140000000001
                     },
                     "html_instructions" : "Head \u003cb\u003eeast\u003c/b\u003e on \u003cb\u003eRedfern Ave.\u003c/b\u003e toward \u003cb\u003eMartello Court\u003c/b\u003e",
                     **"polyline" : {
                        "points" : "woceIvgmd@O}DOkDQqF"**
                     },

So far my application parses this information and simply lists the roads and directions in a list view like this:

enter image description here

What I want to do it highlight the whole route from A to B on a map, however I've found nothing useful online on how to do this on the new Google Maps API v2. I see that polyline's are used instead of overlays to draw lines on Google Maps v2, however from what I can tell, they only draw straight lines which is useless for me. Is there anyway of highlighting the route using the information I have at my disposal (road names, start & end lat-long co-ordinates, polyline points? Any help is appreciated.

Also, I see there is a 'polyline' value in the response which could be useful but I can't work out how to parse or use this bit of information. Does anyone know how I can make sense of this value to plot a polyline?

**"polyline" : {
             "points" : "woceIvgmd@O}DOkDQqF"**

EDIT: My solution code is provided in my answer below.

Jehol answered 7/2, 2013 at 20:49 Comment(0)
J
36

I finally managed to get it working after a lot of trial and error! It now fully highlights a specified route from A to B on a map (as seen in my screenshot below). I have also thrown in my code for anyone who may need it in future.

enter image description here

public class PolyMap extends Activity {
        ProgressDialog pDialog;
        GoogleMap map;
        List<LatLng> polyz;
        JSONArray array;
        static final LatLng DUBLIN = new LatLng(53.344103999999990000,
                -6.267493699999932000);

        @SuppressLint("NewApi")
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.map_layout);
            map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
                    .getMap();
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(DUBLIN, 15));
            map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
            new GetDirection().execute();
        }

        class GetDirection extends AsyncTask<String, String, String> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pDialog = new ProgressDialog(PolyMap.this);
                pDialog.setMessage("Loading route. Please wait...");
                pDialog.setIndeterminate(false);
                pDialog.setCancelable(false);
                pDialog.show();
            }

            protected String doInBackground(String... args) {
                Intent i = getIntent();
                String startLocation = i.getStringExtra("startLoc");
                String endLocation = i.getStringExtra("endLoc");
                            startLocation = startLocation.replace(" ", "+");
                    endLocation = endLocation.replace(" ", "+");;
                String stringUrl = "http://maps.googleapis.com/maps/api/directions/json?origin=" + startLocation + ",+dublin&destination=" + endLocation + ",+dublin&sensor=false";
                StringBuilder response = new StringBuilder();
                try {
                    URL url = new URL(stringUrl);
                    HttpURLConnection httpconn = (HttpURLConnection) url
                            .openConnection();
                    if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        BufferedReader input = new BufferedReader(
                                new InputStreamReader(httpconn.getInputStream()),
                                8192);
                        String strLine = null;

                        while ((strLine = input.readLine()) != null) {
                            response.append(strLine);
                        }
                        input.close();
                    }

                    String jsonOutput = response.toString();

                    JSONObject jsonObject = new JSONObject(jsonOutput);

                    // routesArray contains ALL routes
                    JSONArray routesArray = jsonObject.getJSONArray("routes");
                    // Grab the first route
                    JSONObject route = routesArray.getJSONObject(0);

                    JSONObject poly = route.getJSONObject("overview_polyline");
                    String polyline = poly.getString("points");
                    polyz = decodePoly(polyline);

                } catch (Exception e) {

                }

                return null;

            }

            protected void onPostExecute(String file_url) {

                for (int i = 0; i < polyz.size() - 1; i++) {
                    LatLng src = polyz.get(i);
                    LatLng dest = polyz.get(i + 1);
                    Polyline line = map.addPolyline(new PolylineOptions()
                            .add(new LatLng(src.latitude, src.longitude),
                                    new LatLng(dest.latitude,                dest.longitude))
                            .width(2).color(Color.RED).geodesic(true));

                }
                pDialog.dismiss();

            }
        }

        /* Method to decode polyline points */
        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;
        }
    }
Jehol answered 8/2, 2013 at 3:42 Comment(8)
This help me a lot. thanks. You must consider to save the Polyline line in an Array if you want to reuse the same Map, with that you can delete the Lines from that map.Inelastic
Well there's a co-incidence, I literally spent hours today trying to figure out why line.remove() wasn't working. Thanks!Jehol
Hi @DanCoghlan, why do you have to draw the line between every consecutive 2 points? Can we not draw the polyline for all points at 1 go? - developers.google.com/maps/documentation/android/…Coquillage
@DanCoghlan Hi, I'm new to android, I don't know what I need to give for this String startLocation = i.getStringExtra("startLoc"); String endLocation = i.getStringExtra("endLoc");Acie
startLoc and endLoc are simply the start and end locations entered by the user in some previous activity. The values are passed from the previous activity to the current activity using an intent. In order to retrieve the start and end locations passed in the intent for use in the current activity, you must call the method i.getStringExtra("startLoc"), where startLoc is simply the name I gave to the String variable containing the start loc passed in the intent. In your previous activity, you must have the line i.putExtra("startLoc", Start Location Entered By User) etc.Jehol
latitude longitude coordinates, separated by dots or commas?Sexcentenary
I have everything in place but it seems the origin and destination coordinates are not entered correctly, any help with this?Annulment
@Annulment For future reference as help, just follow the documentation: The address, place ID or textual latitude/longitude value from which you wish to calculate directions can be used as the Origin. Here is a link developers.google.com/maps/documentation/directions/introForestay
A
3

With Android maps api 2 indeed you need to use Polyline class to draw the route on a map (at least it is an easiest way :) ). What you need to do - is to supply list of points along your route.

As for highlighting the active route - there is a handy interface in Polyline class setColor, so you can set whatever color you want to the active route (including an alpha channel)

Polyline line1 = map.addPolyline(new PolylineOptions()
 .add(new LatLng(51.5, -0.1), new LatLng(40.7, -74.0))
 .width(5)
 .color(0xFFFF0000)); //non transparent red

Polyline line2 = map.addPolyline(new PolylineOptions()
 .add(new LatLng(51.5, -0.1), new LatLng(40.8, -74.2))
 .width(5)
 .color(0x7F0000FF)); //semi-transparent blue

Please note you are free to change polyline color anytime you want (f.i. on user click, or something)

As for JSON response from google - route points are encoded, so you can refer to this question to understand how to decode it

Acquire answered 7/2, 2013 at 21:5 Comment(1)
Well, if your road has 10 points in it, polyline will draw 10 (actually 9) straight lines connected to each other.. How many points your route has and what actual coordinates of those points are - this info is encoded into points fieldAcquire
O
2

There is a simple solution

Add a library

compile 'com.google.maps.android:android-maps-utils:0.4+'

reference from https://developers.google.com/maps/documentation/android-api/utility/setup

//Getting the points String from response of NavigationAPI call
String polyz=routeSteps.get(0).getOverview_polyline().getPoints();
//Decoding the LatLng Points using PolyUtil Class used from above Library
List<LatLng> points=PolyUtil.decode(polyz);
polyline.addAll(points);
googleMap.addPolyline(polyline);
Outoftheway answered 5/7, 2016 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.