After reading the recently appeared article
Routes on Google Maps in your Android application , I decided to show another alternative approach to solve this problem. Perhaps he will give a little more insight into working with google-maps and help beginners to quickly deal with this issue.
Get the coordinates
The good news is that google provides us with api to the service for calculating routes between coordinates. Therefore, the general structure of the forthcoming work is approximately as follows:
- We form request with parameters
- We send request and we receive the answer
- Parsim answer
- Draw overlay on maps
Request formation
Full details of how the request looks can be found in the official documentation on
Google developers . Here I will discuss the main aspects. In general, the query looks like this:
http://maps.googleapis.com/maps/api/directions/output?parameters
Where
output can take 2 values:
- json - sets output in the format JavaScript Object Notation (JSON);
- xml - sets output in XML format.
Google itself recommends us to use JSON, and so will I.
parameters are a bunch of different required and not so many parameters that you can specify according to your requirements. I will not speak about the optional parameters, I will say that there are 3 main ones that must be specified without fail:
- origin - the address or textual value of the latitude and longitude of the starting point of the route.
- destination - the address or textual value of the latitude and longitude of the final destination of the route.
- sensor — Indicates whether a route request originates from a device with a location sensor. Valid values ​​are true or false.
Ultimately, the simplest request (from Voronezh to Moscow) with a JSON response looks like this:
http://maps.googleapis.com/maps/api/directions/json?origin=Voronezh&destination=Moscow&sensor=false
I will not give the code to this part, since it is rather trivial to form the line of code you need.
')
Sending a request and getting the result
So, the request is formed, it's time to send. There is probably a bunch of methods for how to execute a request to the service, but I’ll make life easier for myself up to 2 lines, I’ll use the
Spring Framework for android . Well, as you yourself know. I downloaded it, put it in the project, the request looks something like this:
RestTemplate rTemplate = new RestTemplate(); String jsonResponse = rTemplate.getForObject(query, String.class));
Response parsing
We received a response in json format, which contains a lot of different information about the route, but we only need coordinates, on which we will draw our overlay, on this I omit all other results, you can read about them all there, on
Google developers .
Let's parse our json, the code looks something like this:
public ArrayList<Section> parse(JSONObject jsonObject) throws AuthenticationException { ArrayList<Section> list = new ArrayList<Section>(); Location startGeo; Location endGeo; JSONArray results = jsonObject.optJSONArray("routes"); JSONObject route = results.optJSONObject(0); JSONArray legs = route.optJSONArray("legs"); JSONObject leg = legs.optJSONObject(0); JSONArray steps = leg.optJSONArray("steps"); for (int i=0; i < steps.length(); ++i) { JSONObject step = steps.optJSONObject(i); JSONObject startP = step.optJSONObject("start_location"); JSONObject endP = step.optJSONObject("end_location"); JSONObject polyline = step.optJSONObject("polyline"); String encodedPoints = polyline.optString("points"); startGeo = new Location(""); endGeo = new Location(""); startGeo.setLatitude(startP.optDouble("lat")); startGeo.setLongitude(startP.optDouble("lng")); endGeo.setLatitude(endP.optDouble("lat")); endGeo.setLongitude(endP.optDouble("lng")); list.add(new Section(startGeo.getLatitude(), startGeo.getLongitude(), endGeo.getLatitude(), endGeo.getLongitude() , encodedPoints)); } return list; }
The main information that interests us lies in the “steps” array, the structure of which looks like this:
"steps": [ { "travel_mode": "DRIVING", "start_location": { "lat": 41.8507300, "lng": -87.6512600 }, "end_location": { "lat": 41.8525800, "lng": -87.6514100 }, "polyline": { "points": "a~l~Fjk~uOwHJy@P", "levels": "B?B" }, "duration": { "value": 19, "text": "1 min" }, "html_instructions": "Head \u003cb\u003enorth\u003c/b\u003e on \u003cb\u003eS Morgan St\u003c/b\u003e toward \u003cb\u003eW Cermak Rd\u003c/b\u003e", "distance": { "value": 207, "text": "0.1 mi" } }, ...
Each element of the “steps” array contains the “start_location” and “end_location” fields — these are the coordinates of some important, reference points of the route, such as intersections. If you execute a query from Moscow to Voronezh, then there will be about 20 such points. Of course, drawing on 20 points will not work, what should I do? In fact, we should pay attention to the "polyline" field. It contains two more fields “points” and “level”. The content of the “points” looks scary, but in reality these are our coordinates, which are encoded
like this . You should not be afraid, they have already invented everything for us,
we take it and use it. So we get a huge number of coordinates along which we will draw our way. Do not forget that the string "polyline" is contained in each element of the "steps".
Drawing overlay
At the moment we figured out what the request looks like, how you can send it, how to receive and parse the answer. From all this we have a bunch of coordinates along which we need to draw our way. The code might look like this:
private class Road extends Overlay { private ArrayList<GeoPoint> list; private Paint paint; public Road(ArrayList<GeoPoint> list) { this.list = new ArrayList<GeoPoint>(); this.list.addAll(list); paint = new Paint(); paint.setColor(Color.MAGENTA); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(4); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { drawPath(mapView, canvas); } private void drawPath(MapView mv, Canvas canvas) { int x1 = -1; int y1 = -1; int x2 = -1; int y2 = -1; Point point = new Point(); for (int i=0; i < list.size(); i++) { mv.getProjection().toPixels(list.get(i), point); x2 = point.x; y2 = point.y; if (i > 0) { canvas.drawLine(x1, y1, x2, y2, paint); } x1 = x2; y1 = y2; } }
That's all the work. As a result, we can easily get a route between any two points and display it on our map. I hope this article will help you. Good luck.
Once again I will duplicate all links in a handful:
Google direction API - complete information on this service.
Spring framework - a framework for rest request to google service. As an alternative.
Broken line encryption formatHow to decode these your broken lines?