📜 ⬆️ ⬇️

Google MAPs API in android or how to work with maps faster

Many articles have been written about using Google MAPs API, but most of them are so old that it just hurts my eyes. Here I want to tell you about the wonderful library for working with all MAPs API in particular Directions API, as well as about how to integrate all this into the application.

How Google MAPs API works


All documentation for working with maps is available on (logically) the official google maps api website . Today I consider only the Directions API ( documentation ). In order to get any information from a large number, you need to make a request. The answer will come in JSON format.

General view of the request:

http://maps.googleapis.com/maps/api/directions/outputFormat?parameters

Example: https://maps.googleapis.com/maps/api/directions/json?origin=55.754724,%2037.621380&destination=55.728466,%2037.604155&key="Your MAPs API key"
')
Answer
 { "geocoded_waypoints": [ { "geocoder_status": "OK", "place_id": "EjvQmtGA0LDRgdC90LDRjyDQv9C7LiwgMiwg0JzQvtGB0LrQstCwLCDQoNC-0YHRgdC40Y8sIDEwOTAxMg", "types": [ "street_address" ] }, { "geocoder_status": "OK", "place_id": "ChIJ5aZfug5LtUYRGSJyHfEblrk", "types": [ "street_address" ] } ], "routes": [ { "bounds": { "northeast": { "lat": 55.7536656, "lng": 37.6246528 }, "southwest": { "lat": 55.7279873, "lng": 37.6049469 } }, "copyrights": "  2017 Google", "legs": [ { "distance": { "text": "4,4 ", "value": 4434 }, "duration": { "text": "13 .", "value": 777 }, "end_address": " ., 611, , , 119049", "end_location": { "lat": 55.7279873, "lng": 37.6049469 }, "start_address": " ., 2, , , 109012", "start_location": { "lat": 55.7536656, "lng": 37.6225908 }, "steps": [ { "distance": { "text": "0,3 ", "value": 261 }, "duration": { "text": "1 .", "value": 56 }, "end_location": { "lat": 55.7515735, "lng": 37.6240491 }, "html_instructions": "  <b></b>  <b>. </b>   <b>.  C</b>", "polyline": { "points": "mkhsIedsdFHDH@FCHIPUhAcBV_@T_@R[HKFGJGLIPIVIXGVCl@AZ?L?" }, "start_location": { "lat": 55.7536656, "lng": 37.6225908 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,6 ", "value": 585 }, "duration": { "text": "1 .", "value": 78 }, "end_location": { "lat": 55.7463555, "lng": 37.6246528 }, "html_instructions": "   <b>  </b><div style=\"font-size:0.9em\">          </div>", "polyline": { "points": "i~gsIimsdFj@@L?DC@ABEBCDM`A?~BSvBMhAGdAEfAElAED@vBIXAv@Ev@El@Ej@C" }, "start_location": { "lat": 55.7515735, "lng": 37.6240491 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,3 ", "value": 259 }, "duration": { "text": "1 .", "value": 74 }, "end_location": { "lat": 55.7458782, "lng": 37.6206072 }, "html_instructions": " <b></b>  <b>. </b>", "maneuver": "turn-right", "polyline": { "points": "w}fsIaqsdFJ`CRbDPnCJvB\\~D@T@P?F?H" }, "start_location": { "lat": 55.7463555, "lng": 37.6246528 }, "travel_mode": "DRIVING" }, { "distance": { "text": "69 ", "value": 69 }, "duration": { "text": "1 .", "value": 10 }, "end_location": { "lat": 55.7464196, "lng": 37.6201379 }, "html_instructions": "<b>. </b>  <b></b>    <b>. </b>", "polyline": { "points": "wzfsIywrdFAF?BABIN{@f@SJMH" }, "start_location": { "lat": 55.7458782, "lng": 37.6206072 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,4 ", "value": 420 }, "duration": { "text": "1 .", "value": 85 }, "end_location": { "lat": 55.7446178, "lng": 37.6146911 }, "html_instructions": "  <b></b>  <b>. </b>", "maneuver": "turn-slight-left", "polyline": { "points": "c~fsI{trdFOn@I\\CNANAN?^B^Hf@^fAVn@n@lBlAjDhAdDX~@@?Nd@nA|D" }, "start_location": { "lat": 55.7464196, "lng": 37.6201379 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,2 ", "value": 220 }, "duration": { "text": "1 .", "value": 65 }, "end_location": { "lat": 55.7464027, "lng": 37.6131881 }, "html_instructions": " <b></b>  <b>. </b>", "maneuver": "turn-right", "polyline": { "points": "{rfsIyrqdFk@f@GFOJOLaAr@oCtB}@v@" }, "start_location": { "lat": 55.7446178, "lng": 37.6146911 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,1 ", "value": 116 }, "duration": { "text": "1 .", "value": 32 }, "end_location": { "lat": 55.7456823, "lng": 37.6118538 }, "html_instructions": " <b></b>  <b>.  </b>", "maneuver": "turn-left", "polyline": { "points": "_~fsImiqdFRb@J\\Rn@Nd@jArB" }, "start_location": { "lat": 55.7464027, "lng": 37.6131881 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,4 ", "value": 362 }, "duration": { "text": "1 .", "value": 80 }, "end_location": { "lat": 55.7431661, "lng": 37.6150421 }, "html_instructions": " <b></b>  <b>. </b>", "maneuver": "turn-left", "polyline": { "points": "oyfsIaaqdFb@q@dAwAb@q@h@{@PSTWr@cAp@s@nAcA^]z@o@RSO{@" }, "start_location": { "lat": 55.7456823, "lng": 37.6118538 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,2 ", "value": 229 }, "duration": { "text": "1 .", "value": 40 }, "end_location": { "lat": 55.7412352, "lng": 37.6162912 }, "html_instructions": "<b>. </b>  <b></b>    <b>  </b>/<b>.  </b><div style=\"font-size:0.9em\">   .  </div>", "polyline": { "points": "yifsI_uqdF^UJEJERKBATQRO`@YlC_Bf@UVKVK" }, "start_location": { "lat": 55.7431661, "lng": 37.6150421 }, "travel_mode": "DRIVING" }, { "distance": { "text": "79 ", "value": 79 }, "duration": { "text": "1 .", "value": 13 }, "end_location": { "lat": 55.7405459, "lng": 37.616611 }, "html_instructions": "   <b>- </b>", "polyline": { "points": "w}esIy|qdFrBy@TE" }, "start_location": { "lat": 55.7412352, "lng": 37.6162912 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,2 ", "value": 194 }, "duration": { "text": "1 .", "value": 22 }, "end_location": { "lat": 55.7388943, "lng": 37.6156238 }, "html_instructions": "  <b></b>     <b>- </b>", "maneuver": "turn-slight-right", "polyline": { "points": "myesIy~qdFh@N^PtAv@NDzCdB" }, "start_location": { "lat": 55.7405459, "lng": 37.616611 }, "travel_mode": "DRIVING" }, { "distance": { "text": "1,0 ", "value": 1000 }, "duration": { "text": "2 .", "value": 106 }, "end_location": { "lat": 55.73020349999999, "lng": 37.6120644 }, "html_instructions": "   <b>.  </b>", "polyline": { "points": "aoesIsxqdFxDzBlAp@vAx@fBfAzAz@p@\\xAv@VJ`@Rp@THD~Af@bAZnBh@l@Nz@ThARr@J`AFf@Bd@B|@@jB@n@?|@@" }, "start_location": { "lat": 55.7388943, "lng": 37.6156238 }, "travel_mode": "DRIVING" }, { "distance": { "text": "60 ", "value": 60 }, "duration": { "text": "1 .", "value": 9 }, "end_location": { "lat": 55.7296657, "lng": 37.6120519 }, "html_instructions": "   <b>. </b>", "polyline": { "points": "wxcsIkbqdFP?vA@" }, "start_location": { "lat": 55.73020349999999, "lng": 37.6120644 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,2 ", "value": 186 }, "duration": { "text": "1 .", "value": 36 }, "end_location": { "lat": 55.7304209, "lng": 37.6093953 }, "html_instructions": " <b></b>", "maneuver": "turn-right", "polyline": { "points": "mucsIibqdFi@|CUtACL]bBs@jD" }, "start_location": { "lat": 55.7296657, "lng": 37.6120519 }, "travel_mode": "DRIVING" }, { "distance": { "text": "0,4 ", "value": 394 }, "duration": { "text": "1 .", "value": 71 }, "end_location": { "lat": 55.7279873, "lng": 37.6049469 }, "html_instructions": " <b></b><div style=\"font-size:0.9em\">   </div><div style=\"font-size:0.9em\">   </div>", "maneuver": "turn-left", "polyline": { "points": "czcsIwqpdFf@x@dAzAp@|@j@t@j@p@PXNXNb@Nb@\\xA^fAPj@Nb@L`@Nn@Pz@FTHVHR" }, "start_location": { "lat": 55.7304209, "lng": 37.6093953 }, "travel_mode": "DRIVING" } ], "traffic_speed_entry": [], "via_waypoint": [] } ], "overview_polyline": { "points": "mkhsIedsdFRFPMhCyD\\g@RO^Sp@QdAEh@?x@@FEFIDM`A?vFa@nCMtCK|BGvDSj@CJ`Cd@rHl@~IA\\KRoAr@MHOn@Ml@C^B~@Hf@^fAfA|CrDpK~AbFs@n@qFbE}@v@Rb@^lANd@jArBhBiClAmBf@k@r@cAp@s@nBaBnAcAO{@^UVKVMh@a@nDyB~@a@jCeATEh@NtBhAjDjBfGlD~D`ClCxApBbArAh@hBl@rDdAhBd@|B^hBJbBDjFBvA@i@|CYbBqAnGlBtC|ArB|@jA^|@l@|BnAxDr@xCHR" }, "summary": ".  ", "warnings": [], "waypoint_order": [] } ], "status": "OK" } 


As a response, we (expectedly) came JSON with a large set of different points with coordinates and names of these places.

How do you work with this terrible thing?


If you are just starting to work with Android, then I advise you to read about such a wonderful library Retrofit, which turns the work with queries into a code of 2 lines. I will not consider it now.

But today I want to consider an example of using the Java Client for Google Maps Services library. The library is wonderful for me, it frees you from having to write (even if very short) requests manually and is great in cases when you need to write very quickly, such as on a hackathon. I want to show a live example of using this library on the example of working with the Directions API.

Library connection


First we need to get the key for our application. Stamp at the office. website , we find the “get the key” button on top, create a new project, click next and you're done!
UPD: now you can not get free. Since the summer of 2018, Google has updated the plan and you must enter your card details to get $ 200 for requests each month for free. This should be enough, but of course the trend is not happy.

Firebase
For the application to work properly, we need to get the file google-service.json. Go to the firebase, select our project and add it. Next we need to select the Android project, enter the name of the package, register the application. Download the file and drag it to the app folder. By the way, it will not be visible in the project tree, for this you need to change the display in Android Studio from Android to Project or get into our project through the file manager. Next, follow the instructions where to write what code.

Enable in console
We also need to enable the Directions API (or any other API you need) in the console, to do this, go here , select our application and enable the Directions API.

Gradle
In Gradle files, you also need to add a couple more lines. As a result, the new lines look like this:

Project.gradle

 dependencies { ... classpath 'com.google.gms:google-services:3.1.0' } ... repositories { jcenter() mavenCentral() } 

app.gradle
 dependencies { ... compile 'com.google.maps:google-maps-services:0.2.4' compile 'com.google.android.gms:play-services-maps:11.0.4' compile 'org.slf4j:slf4j-nop:1.7.25' } apply plugin: 'com.google.gms.google-services' 

Be sure to check if it is the current version!

We embed the map in the application


Google map in android is implemented as a fragment (or as a MapView, but about that another time, we do not have much difference now). Just embed it in our layout. In our class, which works with the map, you need to find this map and implement the interface.

The code for the fragment looks like this. I will work with the MainActivity, so if you use another class you need to change the context.

  <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" tools:context=".MainActivity"/> 

Great, the fragment was embedded, Android Studio does not swear at us, we go further. Go to MainActivity.class and implement the OnMapReadyCallback interface.

 implements OnMapReadyCallback ... @Override public void onMapReady(GoogleMap googleMap) { ... } 

Write to onCreate

 SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); 

We also go to Manifests and register such things inside the application tag.

 <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> 

Where instead of @string/google_maps_key , your key for maps that we received earlier should be substituted. Accordingly, you need to create the necessary resource in the string file.

<string name="google_maps_key">...</string>

We write all sorts of interesting


Great, we have a map, let's finally write at least something interesting. Let our goal be to draw a route in Moscow through several points:


I put all our places in the List and do it as a global variable.

 private List<LatLng> places = new ArrayList<>(); 

In onCreate

 places.add(new LatLng(55.754724, 37.621380)); places.add(new LatLng(55.760133, 37.618697)); places.add(new LatLng(55.764753, 37.591313)); places.add(new LatLng(55.728466, 37.604155)); 

To begin, create a marker for each place. A marker is simply an object to which coordinates are transmitted, and then they are superimposed on the map. Code:

 MarkerOptions[] markers = new MarkerOptions[places.size()]; for (int i = 0; i < places.size(); i++) { markers[i] = new MarkerOptions() .position(places.get(i)); googleMap.addMarker(markers[i]); } 

Next, we write this code all in the same onMapReady method

 //   , mapsApiKey    String     GeoApiContext geoApiContext = new GeoApiContext.Builder() .apiKey(mapsApiKey) .build(); //         DirectionsResult result = null; try { result = DirectionsApi.newRequest(geoApiContext) .origin(places.get(0))//  .destination(places.get(places.size() - 1))//  .waypoints(places.get(1), places.get(2)).await();// . ,   ,   ,    } catch (ApiException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //      List<com.google.maps.model.LatLng> path = result.routes[0].overviewPolyline.decodePath(); //    PolylineOptions line = new PolylineOptions(); LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder(); //   ,    Polyline   LanLngBounds.Builder for (int i = 0; i < path.size(); i++) { line.add(new com.google.android.gms.maps.model.LatLng(path.get(i).lat, path.get(i).lng)); latLngBuilder.include(new com.google.android.gms.maps.model.LatLng(path.get(i).lat, path.get(i).lng)); } //     line.width(16f).color(R.color.colorPrimary); //    googleMap.addPolyline(line); //      LatLngBounds latLngBounds = latLngBuilder.build(); CameraUpdate track = CameraUpdateFactory.newLatLngBounds(latLngBounds, width, width, 25);//width     googleMap.moveCamera(track); 

When launching the application, we got the following picture:

Android phone screenshot with transport mode path

Hmm, Moscow, of course, very tangled, but not so much. Why did such a strange route give us back Google? Because he built a route for cars, which goes by default, but we can change that. To build a route for pedestrians, change the code to:

 try { result = DirectionsApi.newRequest(geoApiContext) .mode(TravelMode.WALKING)//: ", .   " .origin(places.get(0)) .destination(places.get(places.size() - 1)) .waypoints(places.get(1), places.get(2)).await(); ... 

Now our route looks like this.

Android phone screenshot with walking mode path

There are many more settings, all of them can be found in the documentation . Simply, we will add all the parameters not to the raw query, but to the code, since the library methods have the same names as simply in the queries.

All code is on github .

Source: https://habr.com/ru/post/341548/


All Articles