Home Development for Android Google MAPs API in android or how to work with maps faster

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

by admin

I have written many articles on the use of Google MAPs API, but most of them are so outdated that it just hurts my eyes. Here I want to share a great library for working with all the MAPs API, especially the Directions API, as well as how to integrate it into an application.

How Google MAPs API works

All the documentation for working with maps is at (logically) The official google maps api website Today I’m only looking at 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.
Query view :
http://maps.googleapis.com/maps/api/directions/outputFormat?parameters
Example : https://maps.googleapis.com/maps/api/directions/json?origin=55.754724, %2037.621380destination=55.728466, %2037.604155key="Your MAPs API key"
Reply

{"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": "Cartographic Data 2017 Google", "legs": [{"distance": {"text": "4.4 km", "value": 4434}, "duration": {"text": "13 min.", "value": 777}, "end_address": "Leninsky ave., 6c11, Moscow, Russia, 119049", "end_location": {"lat": 55.7279873, "lng": 37.6049469}, "start_address": "Krasnaya pl., 2, Moscow, Russia, 109012", "start_location": {"lat": 55.7536656, "lng": 37.6225908}, "steps": [{"distance": {"text": "0.3 km", "value": 261}, "duration": {"text": "1 min;", "value": 56}, "end_location": {"lat": 55.7515735, "lng": 37.6240491}, "html_instructions": "Go to <b> South</b> on <b> Red square</b> toward <b> PL. Vasilevsky Descent</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 km", "value": 585}, "duration": {"text": "1 min;", "value": 78}, "end_location": {"lat": 55.7463555, "lng": 37.6246528}, "html_instructions": "Continue driving on <b> Bolshoy Moskvoretsky</b> <div style="font-size:0.9em"> Sections of this road may be closed on certain days or hours</div> ", "polyline": {"points": "i~gsIimsdFj@@L?DC@ABEBCDM`A?~BSvBhMhAGdAEfAElAED@vBIXAv@Ev@El@Ej@C"}, "start_location": {"lat": 55.7515735, "lng": 37.6240491}, "travel_mode": "DRIVING"}, {"distance": {"text": "0.3 km", "value": 259}, "duration": {"text": "1 min.", "value": 74}, "end_location": {"lat": 55.7458782, "lng": 37.6206072}, "html_instructions": "turn <b> right</b> onto <b> Bolotnaya</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 m", "value": 69}, "duration": {"text": "1 min.", "value": 10}, "end_location": {"lat": 55.7464196, "lng": 37.6201379}, "html_instructions": "b> Bolotnaya St.</b> turns <b> to the right</b> and goes to <b> lane. Faleevsky</b> ", "polyline": {"points": "wzfsIywrdFAF?BABIN{@f@SJMH"}, "start_location": {"lat": 55.7458782, "lng": 37.6206072}, "travel_mode": "DRIVING"}, {"distance": {"text": "0.4 km", "value": 420}, "duration": {"text": "1 min.", "value": 85}, "end_location": {"lat": 55.7446178, "lng": 37.6146911}, "html_instructions": "Smooth turn<b> to the left</b> on <b> Bolotnaya Square</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 km", "value": 220}, "duration": {"text": "1 min.", "value": 65}, "end_location": {"lat": 55.7464027, "lng": 37.6131881}, "html_instructions": "Turn <b> to the right</b> on <b> Serafimovich St.</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 km", "value": 116}, "duration": {"text": "1 min.", "value": 32}, "end_location": {"lat": 55.7456823, "lng": 37.6118538}, "html_instructions": "Turn<b> left</b> on <b> Sofiyskaya embankment St.</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 km", "value": 362}, "duration": {"text": "1 min.", "value": 80}, "end_location": {"lat": 55.7431661, "lng": 37.6150421}, "html_instructions": "turn <b> left</b> onto <b> Serafimovicha</b> ", "maneuver": "turn-left", "polyline": {"points": "oyfsIaaqdFb@q@dAwAb@q@q@h@{@PSTWr@cAp@s@nAcA^]z@o@RSO{@"}, "start_location": {"lat": 55.7456823, "lng": 37.6118538}, "travel_mode": "DRIVING"}, {"distance": {"text": "0.2 km", "value": 229}, "duration": {"text": "1 min.", "value": 40}, "end_location": {"lat": 55.7412352, "lng": 37.6162912}, "html_instructions": "<b> Serafimovicha</b> street turns <b> right</b> and passes into <b> Small Stone Bridge</b> /<b> ul. Bolshaya Polyanka</b> <div style="font-size:0.9em"> Continue on Bolshaya Polyanka Street</div> ""polyline": {"points": "yifsI_uqdF^UJEJERKBATQRO`@YlC_Bf@UVKVK"}, "start_location": {"lat": 55.7431661, "lng": 37.6150421}, "travel_mode": "DRIVING"}, {"distance": {"text": "79 m", "value": 79}, "duration": {"text": "1 min.", "value": 13}, "end_location": {"lat": 55.7405459, "lng": 37.616611}, "html_instructions": "Keep moving along <b> Yakimansky Ave</b>", "polyline": {"points": "w}esIy|qdFrBy@TE"}, "start_location": {"lat": 55.7412352, "lng": 37.6162912}, "travel_mode": "DRIVING"}, {"distance": {"text": "0.2 km", "value": 194}, "duration": {"text": "1 min.", "value": 22}, "end_location": {"lat": 55.7388943, "lng": 37.6156238}, "html_instructions": "Smoothly turn <b> to the right</b> and continue driving along <b> Yakimansky Ave</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 km", "value": 1000}, "duration": {"text": "2 min.", "value": 106}, "end_location": {"lat": 55.73020349999999, "lng": 37.6120644}, "html_instructions": "Continue driving along <b> st. Bolshaya Yakimanka</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 m", "value": 60}, "duration": {"text": "1 min.", "value": 9}, "end_location": {"lat": 55.7296657, "lng": 37.6120519}, "html_instructions": "Keep moving along <b> Kaluzhskaya Square</b>", "polyline": {"points": "wxcsIkbqdFP?vA@"}, "start_location": {"lat": 55.73020349999999, "lng": 37.6120644}, "travel_mode": "DRIVING"}, {"distance": {"text": "0.2 km", "value": 186}, "duration": {"text": "1 min.", "value": 36}, "end_location": {"lat": 55.7304209, "lng": 37.6093953}, "html_instructions": "Turn <b> to the right</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 km", "value": 394}, "duration": {"text": "1 min.", "value": 71}, "end_location": {"lat": 55.7279873, "lng": 37.6049469}, "html_instructions": "Turn<b> to the left</b><div style="font-size:0.9em"> Restricted access road</div><div style="font-size:0.9em"> The destination will be on the right</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": "Bolshaya Yakimanka Street", "warnings": [], "waypoint_order": []}], "status": "OK"}

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

How do you even work with this scary stuff?

If you are just starting to work with Android, then I advise you to read about this wonderful library Retrofit, which turns the work with requests in the code of 2 lines. I won’t go through it now.
But today I want to look at an example of using the library Java Client for Google Maps Services I think the library is great, it frees me from having to write (even very short) queries by hand and is great when you need to write very quickly, such as at a hackathon. I want to show you a live example of how to use this library with Directions API.

Connecting the library

First we need to get a key for our application. Let’s go to official site , find the "get key" button at the top, create a new project, click next and it’s done!
UPD: now you can’t get it for free. As of summer 2018, Google updated the plan and you have to enter your card information to get $200 for queries every month for free. That should be enough, but of course the trend is not happy.
Firebase
We need to get the google-service.json file for the application to work properly. Go to 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 and drop it into 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 enter our project through the file manager. Then follow the instructions where to write what code.
Enable in the console
We also need to enable the Directions API (or any other API you need) in the console, to do that go to here select our application and switch on the Directions API.
Gradle
In the Gradle files 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 this is the current version!

Embedding the map in the application

Google map in Android is implemented as a snippet (or as MapView, but about that another time, we don’t really care right now). We just embed it in our layout. In our class that handles the map, we need to find this map and implement the interface.
The code for the snippet looks like this. I will work with 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, we’ve embedded the snippet, Android Studio doesn’t swear at us, let’s move on. Go to MainActivity.class and implement the OnMapReadyCallback interface.

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

In onCreate we write

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

Also go to Manifests and write things like this inside tag application

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

Where instead of @string/google_maps_key must substitute your key for the maps, which we got earlier. Accordingly, you need to create the right resource in the string file.
<string name="google_maps_key"> ...</string>

Write all sorts of interesting things

Ok, we have a map, let’s write some interesting stuff. Let our goal be to draw a route around Moscow through some points :

  • Gum (55.754724, 37.621380)
  • Bolshoi Theater (55.760133, 37.618697)
  • Patriarch’s Ponds (55.764753, 37.591313)
  • Culture Park (55.728466, 37.604155)

I put all our places in List and make 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));

First, let’s create a marker for each location. A marker is just an object to which coordinates are passed, and then they are overlaid 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]);}

Then we write the following code in the same onMapReady method

//Get the context for queries, mapsApiKey stores a String with the key for mapsGeoApiContext geoApiContext = new GeoApiContext.Builder().apiKey(mapsApiKey).build();//Here will be our final path consisting of a set of pointsDirectionsResult result = null;try {result = DirectionsApi.newRequest(geoApiContext).origin(places.get(0))//start location.destination(places.get(places.size() - 1))//destination point.waypoints(places.get(1), places.get(2)).await();//Intermediate points. Yes, it's not very nice, you can do it through a loop, but it's clear.} catch (ApiException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}//Converting the final path to a set of pointsList<com.google.maps.model.LatLng> path = result.routes[0].overviewPolyline.decodePath();//Line to be drawnPolylineOptions line = new PolylineOptions();LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder();//Walk through all points, add them to Polyline and to LanLngBounds.Builderfor (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))}//make the line more or less prettyline.width(16f).color(R.color.colorPrimary);//Add the line to the mapgoogleMap.addPolyline(line);//Position the camera at the position we wantLatLngBounds latLngBounds = latLngBuilder.build();CameraUpdate track = CameraUpdateFactory.newLatLngBounds(latLngBounds, width, width, 25);//width is the size of our screengoogleMap.moveCamera(track);

When we run the application, we get this picture :
Google MAPs API in android or how to work with maps faster
Hmm, Moscow is certainly quite confusing, but not that confusing. So why did Google give us such a weird route back? Because it built a route for cars that goes by default, but we can change that. To build a route for pedestrians, we change the code to :

try {result = DirectionsApi.newRequest(geoApiContext).mode(TravelMode.WALKING)//We say: "No, thank you. I'll walk".origin(places.get(0)).destination(places.get(places.size() - 1)).waypoints(places.get(1), places.get(2)).await();...

Now our route looks like this
Google MAPs API in android or how to work with maps faster
There are many more settings, you can read about them all at documentation It’s just that we’ll be adding all the parameters not in the raw query, but in the code, since the library methods have the same names as just in the queries.
All the code is at github

You may also like