Click here to Skip to main content
15,892,005 members
Articles / Mobile Apps / Android / Android4

Google Maps Nearby Places API using Retrofit Android

Rate me:
Please Sign up or sign in to vote.
4.64/5 (3 votes)
29 Aug 2016CPOL8 min read 25.6K   2   2
Google Maps Nearby Places API Hello Guys. Hope all of you are doing well. In this tutorial, we will learn how to add the markers on nearby places in Google Maps API using Retrofit . We will name this App as Google Maps Nearby Places API.

Hello Guys. Hope all of you are doing well. In this tutorial, we will learn how to add the markers on nearby places in Google Maps API using Retrofit . We will name this App as Google Maps Nearby Places API. You can see demo of this tutorial in above video. This is one of the most crystal clear tutorials where minimum code is used to implement nearby places app using retrofit. We made a similar tutorial on Google Maps Search Nearby, but that was implemented using Async Task. Now Async task has become pretty much mediocre and people are using Retrofit to capture data from URL, So we made this tutorial on similar lines. Now you don’t have to make any JSON Parser or Data capture class. Retrofit Android automatically takes care of it.

Pre-requisites

1) Android Studio installed on your PC (Unix or Windows).
2) A real time android device (Smartphone or Tablet) configured with Android Studio.
3) A basic knowledge of Android lifecycle and different classes & functions used in Android Studio.

Now let’s make it. We hope you would have already made an App to display current user location.

Creating new project

Please follow following steps:

Google_Map_Activity

  1. Open Android Studio and make a new project with name “Google Maps Retrofit” or “Google Maps Nearby Places API” and company domain application.example.com (I used my company domain i.e androidtutorialpoint.com. Similarly you can use yours).
  2. Click Next and choose android version Lollipop. Again Click Next and Choose Google Maps Activity (as shown in following pic).
  3. Leave all things remaining same and Click Finish.

Now you will be able to see three files:

  1. google_maps_api.xml (…/GoogleMapsSearchNearby/app/src/debug/res/values/google_maps_api.xml)
  2. MapsActivity.java (…/GoogleMapsSearchNearby/app/src/main/java/com/androidtutorialpoint/googlemapssearchnearby
    /MapsActivity.java
    )
  3. AndroidManifest.xml ( …/GoogleMapsSearchNearby/app/src/main/AndroidManifest.xml)

Open google_maps_api.xml. Here you will find a lot of information along with a link. Copy-Paste this link in your web browser. Make a Gmail account through which you will configure google play services.

Google Maps Search Nearby

Now at the browser choose “Create New Project” and Click Continue. Following screen will be displayed:

Google Maps Search Nearby

Click on Go to credentials. Below screen will appear.

Google Maps Nearby Places API

Create your key by clicking Create. Now a key will be created but there is one big change here as compared to our previous Google Maps tutorials. Here you will need a Server Key. So to generate a Server Key click on Create Credentials and then API Key as shown in the following image:

Google Maps Nearby Places API

Click on Server Key. Below screen will appear:

Google Maps Nearby Places API

Click Create and copy the Server Key generated. You shall copy and paste this key in google_maps_api.xml. Copy paste it in place where YOUR_KEY_HERE is written:

Code inside google_maps_api.xml is complete.

google_maps_api.xml

XML
<resources>
    <!--
    TODO: Before you run your application, you need a Google Maps API key.

    To get one, follow this link, follow the directions and press "Create" at the end:

    https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx%com.androidtutorialpoint.googlemapsapp

    You can also add your credentials to an existing key, using this line:
    xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx;com.androidtutorialpoint.googlemapsapp

    Alternatively, follow the directions here:
    https://developers.google.com/maps/documentation/android/start#get-key

    Once you have your key (it starts with "AIza"), replace the "google_maps_key"
    string in this file.
    -->
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">LVwrKoLOEMgwUBXGiut0bkFhoAjOiaVemoMlymg</string>     
</resources>

Code Inside AndroidManifest.xml

If you go inside AndroidManifest.xml then this key will be displayed in meta tags. Here you need to add permissions for accessing location of device. The required permission should be as follows:

ACCESS_NETWORK_STATE – To check network state i.e if we are connected to any network or not.
INTERNET – If we are connected to Internet or not.
ACCESS_COARSE_LOCATION – To determine user’s location using WiFi and mobile. It will give us an approximate location.
ACCESS_FINE_LOCATION – To determine user’s location using GPS. It will give us precise location.
OpenGL ES V2 – Required for Google Maps V2

AndroidManifest.xml

XML
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.androidtutorialpoint.googlemapsdrawroute"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the 'MyLocation' functionality. 
    -->
    <uses-permission android:name="com.androidtutorialpoint.mymapsappsdirection.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!--
             The API key for Google Maps Nearby Places API is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key"/>

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Code inside activity_maps.xml

Here we will add three buttons each for Restaurant, Hospitals and Schools such that when user clicks on Restaurant then markers will be added on nearby restaurants. Similarly in case of other two buttons. For this, we will use FrameLayout . Refer below code:

activity_maps.xml

XML
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

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

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <Button
        android:id="@+id/btnRestaurant"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nearby Restaurants" />

    <Button
        android:id="@+id/btnHospital"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nearby Hospitals" />

    <Button
        android:id="@+id/btnSchool"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nearby Schools" />

    <TextView
        android:id="@+id/tv_lat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_lng"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
</FrameLayout>

Note: Please see your build.gradle file. It should have following code:

XML
dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services:8.4.0'
    compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
    compile 'com.google.code.gson:gson:1.7.2'
    compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
    compile 'com.squareup.okhttp:okhttp:2.4.0'

}

Fourth line compile ‘com.google.android.gms:play-services:8.4.0’ is responsible for inserting Google Play Services. Please make sure this line is present in build.gradle. Remaining lines after 4th line are responsible for adding Retrofit Android library files. Sync the Project.

Implementation of Google Maps using Retrofit

This is what will return by Google Server while we search for nearby places around current location of user. As you could see in the link we have JSON Object and Array as data returned from Google Maps. We have to capture this data in our App and accordingly add marker at each location. To capture this data using Retrofit Android, we have to make POJO Class. This class is actually composed of Getter and Setter methods.

Adding POJO Class

Add following classes in a separate folder named POJO at path …/GoogleMapsRetrofit/app/src/main/java/com/androidtutorialpoint/googlemapsretrofit/POJO

Example.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

public class Example {

    @SerializedName("html_attributions")
    @Expose
    private List<Object> htmlAttributions = new ArrayList<Object>();
    @SerializedName("next_page_token")
    @Expose
    private String nextPageToken;
    @SerializedName("results")
    @Expose
    private List<Result> results = new ArrayList<Result>();
    @SerializedName("status")
    @Expose
    private String status;

    /**
     *
     * @return
     * The htmlAttributions
     */
    public List<Object> getHtmlAttributions() {
        return htmlAttributions;
    }

    /**
     *
     * @param htmlAttributions
     * The html_attributions
     */
    public void setHtmlAttributions(List<Object> htmlAttributions) {
        this.htmlAttributions = htmlAttributions;
    }

    /**
     *
     * @return
     * The nextPageToken
     */
    public String getNextPageToken() {
        return nextPageToken;
    }

    /**
     *
     * @param nextPageToken
     * The next_page_token
     */
    public void setNextPageToken(String nextPageToken) {
        this.nextPageToken = nextPageToken;
    }

    /**
     *
     * @return
     * The results
     */
    public List<Result> getResults() {
        return results;
    }

    /**
     *
     * @param results
     * The results
     */
    public void setResults(List<Result> results) {
        this.results = results;
    }

    /**
     *
     * @return
     * The status
     */
    public String getStatus() {
        return status;
    }

    /**
     *
     * @param status
     * The status
     */
    public void setStatus(String status) {
        this.status = status;
    }

}

Location.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Location {

    @SerializedName("lat")
    @Expose
    private Double lat;
    @SerializedName("lng")
    @Expose
    private Double lng;

    /**
     *
     * @return
     * The lat
     */
    public Double getLat() {
        return lat;
    }

    /**
     *
     * @param lat
     * The lat
     */
    public void setLat(Double lat) {
        this.lat = lat;
    }

    /**
     *
     * @return
     * The lng
     */
    public Double getLng() {
        return lng;
    }

    /**
     *
     * @param lng
     * The lng
     */
    public void setLng(Double lng) {
        this.lng = lng;
    }

}

Geometry.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Geometry {

    @SerializedName("location")
    @Expose
    private Location location;

    /**
     *
     * @return
     * The location
     */
    public Location getLocation() {
        return location;
    }

    /**
     *
     * @param location
     * The location
     */
    public void setLocation(Location location) {
        this.location = location;
    }

}

Result.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

public class Result {

    @SerializedName("geometry")
    @Expose
    private Geometry geometry;
    @SerializedName("icon")
    @Expose
    private String icon;
    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("opening_hours")
    @Expose
    private OpeningHours openingHours;
    @SerializedName("photos")
    @Expose
    private List<Photo> photos = new ArrayList<Photo>();
    @SerializedName("place_id")
    @Expose
    private String placeId;
    @SerializedName("rating")
    @Expose
    private Double rating;
    @SerializedName("reference")
    @Expose
    private String reference;
    @SerializedName("scope")
    @Expose
    private String scope;
    @SerializedName("types")
    @Expose
    private List<String> types = new ArrayList<String>();
    @SerializedName("vicinity")
    @Expose
    private String vicinity;
    @SerializedName("price_level")
    @Expose
    private Integer priceLevel;

    /**
     *
     * @return
     * The geometry
     */
    public Geometry getGeometry() {
        return geometry;
    }

    /**
     *
     * @param geometry
     * The geometry
     */
    public void setGeometry(Geometry geometry) {
        this.geometry = geometry;
    }

    /**
     *
     * @return
     * The icon
     */
    public String getIcon() {
        return icon;
    }

    /**
     *
     * @param icon
     * The icon
     */
    public void setIcon(String icon) {
        this.icon = icon;
    }

    /**
     *
     * @return
     * The id
     */
    public String getId() {
        return id;
    }

    /**
     *
     * @param id
     * The id
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     *
     * @return
     * The name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     * The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     * The openingHours
     */
    public OpeningHours getOpeningHours() {
        return openingHours;
    }

    /**
     *
     * @param openingHours
     * The opening_hours
     */
    public void setOpeningHours(OpeningHours openingHours) {
        this.openingHours = openingHours;
    }

    /**
     *
     * @return
     * The photos
     */
    public List<Photo> getPhotos() {
        return photos;
    }

    /**
     *
     * @param photos
     * The photos
     */
    public void setPhotos(List<Photo> photos) {
        this.photos = photos;
    }

    /**
     *
     * @return
     * The placeId
     */
    public String getPlaceId() {
        return placeId;
    }

    /**
     *
     * @param placeId
     * The place_id
     */
    public void setPlaceId(String placeId) {
        this.placeId = placeId;
    }

    /**
     *
     * @return
     * The rating
     */
    public Double getRating() {
        return rating;
    }

    /**
     *
     * @param rating
     * The rating
     */
    public void setRating(Double rating) {
        this.rating = rating;
    }

    /**
     *
     * @return
     * The reference
     */
    public String getReference() {
        return reference;
    }

    /**
     *
     * @param reference
     * The reference
     */
    public void setReference(String reference) {
        this.reference = reference;
    }

    /**
     *
     * @return
     * The scope
     */
    public String getScope() {
        return scope;
    }

    /**
     *
     * @param scope
     * The scope
     */
    public void setScope(String scope) {
        this.scope = scope;
    }

    /**
     *
     * @return
     * The types
     */
    public List<String> getTypes() {
        return types;
    }

    /**
     *
     * @param types
     * The types
     */
    public void setTypes(List<String> types) {
        this.types = types;
    }

    /**
     *
     * @return
     * The vicinity
     */
    public String getVicinity() {
        return vicinity;
    }

    /**
     *
     * @param vicinity
     * The vicinity
     */
    public void setVicinity(String vicinity) {
        this.vicinity = vicinity;
    }

    /**
     *
     * @return
     * The priceLevel
     */
    public Integer getPriceLevel() {
        return priceLevel;
    }

    /**
     *
     * @param priceLevel
     * The price_level
     */
    public void setPriceLevel(Integer priceLevel) {
        this.priceLevel = priceLevel;
    }

}

Photo.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

public class Photo {

    @SerializedName("height")
    @Expose
    private Integer height;
    @SerializedName("html_attributions")
    @Expose
    private List<String> htmlAttributions = new ArrayList<String>();
    @SerializedName("photo_reference")
    @Expose
    private String photoReference;
    @SerializedName("width")
    @Expose
    private Integer width;

    /**
     *
     * @return
     * The height
     */
    public Integer getHeight() {
        return height;
    }

    /**
     *
     * @param height
     * The height
     */
    public void setHeight(Integer height) {
        this.height = height;
    }

    /**
     *
     * @return
     * The htmlAttributions
     */
    public List<String> getHtmlAttributions() {
        return htmlAttributions;
    }

    /**
     *
     * @param htmlAttributions
     * The html_attributions
     */
    public void setHtmlAttributions(List<String> htmlAttributions) {
        this.htmlAttributions = htmlAttributions;
    }

    /**
     *
     * @return
     * The photoReference
     */
    public String getPhotoReference() {
        return photoReference;
    }

    /**
     *
     * @param photoReference
     * The photo_reference
     */
    public void setPhotoReference(String photoReference) {
        this.photoReference = photoReference;
    }

    /**
     *
     * @return
     * The width
     */
    public Integer getWidth() {
        return width;
    }

    /**
     *
     * @param width
     * The width
     */
    public void setWidth(Integer width) {
        this.width = width;
    }

}

OpeningHours.java

Java
package com.androidtutorialpoint.googlemapsretrofit.POJO;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

public class OpeningHours {

    @SerializedName("open_now")
    @Expose
    private Boolean openNow;
    @SerializedName("weekday_text")
    @Expose
    private List<Object> weekdayText = new ArrayList<Object>();

    /**
     *
     * @return
     * The openNow
     */
    public Boolean getOpenNow() {
        return openNow;
    }

    /**
     *
     * @param openNow
     * The open_now
     */
    public void setOpenNow(Boolean openNow) {
        this.openNow = openNow;
    }

    /**
     *
     * @return
     * The weekdayText
     */
    public List<Object> getWeekdayText() {
        return weekdayText;
    }

    /**
     *
     * @param weekdayText
     * The weekday_text
     */
    public void setWeekdayText(List<Object> weekdayText) {
        this.weekdayText = weekdayText;
    }

}

File structure will finally look like this:

Google Maps Nearby Places API Files

These POJO classes will be used to get data from URL from its “get” functions. We will see this later.

Interface Declaration

Make a new interface named RetrofitMaps.java and add following code:

package com.androidtutorialpoint.googlemapsretrofit;

import com.androidtutorialpoint.googlemapsretrofit.POJO.Example;

import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Query;

/**
 * Created by navneet on 17/7/16.
 */
public interface RetrofitMaps {

    /*
     * Retrofit get annotation with our URL
     * And our method that will return us details of student.
     */
    @GET("api/place/nearbysearch/json?sensor=true&key=AIzaSyDN7RJFmImYAca96elyZlE5s_fhX-MMuhk")
    Call<Example> getNearbyPlaces(@Query("type") String type, @Query("location") String location, @Query("radius") int radius);

}

Let’s have a look at above interface. @GET is used to call server (corresponding to URL). It is predefined part of Retrofit android library, only end part of URL will be added here. Here we have added key and sensor as part of the URL while rest of the variable (like location and radius) will be passed at run time using Query in getNearbyPlaces(). getNearbyPlaces method is used to get details of the points returned from Google Server and Example is a POJO class to store that response. One more point to note down here is location coordinates passed in getNearbyPlaces will be current location of the user as we will see later. Corresponding to these coordinates, Google will return nearby places location.

MapsActivity.java Code of Google Maps Search Nearby App

As you know, this is heart of our Google Maps Nearby Places API and hence it needs special attention. Here we will first build Retrofit and then will add Markers at the points returned by getter methods of POJO Class. Here we won’t discuss code related to getting current user location.

First of all, we will check if Google Play Services available or not in onCreate() function of MainActivity.java. For that we will use function CheckGooglePlayServices().

CheckGooglePlayServices()

private boolean CheckGooglePlayServices() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(this);
        if(result != ConnectionResult.SUCCESS) {
            if(googleAPI.isUserResolvableError(result)) {
                googleAPI.getErrorDialog(this, result,
                        0).show();
            }
            return false;
        }
        return true;
    }

GoogleApiAvailability is the Helper class for verifying that the Google Play services APK is available and up-to-date on android device. If result is ConnectionResult.SUCCESS then connection was successful otherwise, we will return false.

Now comes the most important part of our Google Maps Nearby Places API code i.e. onMapReady() function. Here we will first build a Google API Client and then enable current user location using mMap.setMyLocationEnabled(true).

buildGoogleApiClient

protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

So now we will directly refer to the working of buttons and how to get nearby places using it. I will explain here functionality of Nearby Restaurants button. Rest of the two buttons will share same functionality except string passed will be Hospital or School according to button clicked.

Finding nearby Restaurants on Google Maps

We will start its implementation by setting setOnClickListener() and as soon as user clicks on it, code inside onClick(View v) executed.

Button btnRestaurant = (Button) findViewById(R.id.btnRestaurant);
        btnRestaurant.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                build_retrofit_and_get_response("restaurant");
            }
        });

Build Retrofit and add Markers

Here we will build Retrofit and add markers at the points returned by Google Server. Add following code in function build_retrofit_and_get_response().

private void build_retrofit_and_get_response(String type) {

        String url = "https://maps.googleapis.com/maps/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        RetrofitMaps service = retrofit.create(RetrofitMaps.class);

        Call<Example> call = service.getNearbyPlaces(type, latitude + "," + longitude, PROXIMITY_RADIUS);

        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(Response<Example> response, Retrofit retrofit) {

                try {
                    mMap.clear();
                    // This loop will go through all the results and add marker on each location.
                    for (int i = 0; i < response.body().getResults().size(); i++) {
                        Double lat = response.body().getResults().get(i).getGeometry().getLocation().getLat();
                        Double lng = response.body().getResults().get(i).getGeometry().getLocation().getLng();
                        String placeName = response.body().getResults().get(i).getName();
                        String vicinity = response.body().getResults().get(i).getVicinity();
                        MarkerOptions markerOptions = new MarkerOptions();
                        LatLng latLng = new LatLng(lat, lng);
                        // Position of Marker on Map
                        markerOptions.position(latLng);
                        // Adding Title to the Marker
                        markerOptions.title(placeName + " : " + vicinity);
                        // Adding Marker to the Camera.
                        Marker m = mMap.addMarker(markerOptions);
                        // Adding colour to the marker
                        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                        // move map camera
                        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
                        mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
                    }
                } catch (Exception e) {
                    Log.d("onResponse", "There is an error");
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Throwable t) {
                Log.d("onFailure", t.toString());
            }
        });
}

In the above code we build Retrofit using Retrofit.Builder() and converted JSON data into accessible data object using GsonConverterFactory. You can read more about GSON. After this we passed our interface RetrofitMaps to the retrofit to get details of the nearby places. Now comes the last but most important part i.e. Executing call and adding marker on each point on Google Maps Nearby Places API.

Calls may be executed synchronously with execute(), or asynchronously with enqueue(). enqueue() will Asynchronously send the request and notify callback of its response or if an error occurred talking to the server, creating the request, or processing the response. If response comes then onResponse will be automatically called. If response doesn’t come out then onFailure will be called and reason of failure will be printed.
While calling getNearbyPlaces we are passing latitude and longitude coordinates of current location of user. Also PROXIMITY_RADIUS is provided to search nearby places only under that radius. After getting response from server onResponse is called automatically. In this method we first cleared Google Maps using mMap.clear() so that any pre-deposited markers are deleted. Then a loop is inititated to get every nearby place and one by one marker is added at each location. We get the coordinates of nearby places through getter methods defined in POJO Classes. For Example to get the longitude and latitude we used getLat() and getLng() from Location.java.

So finally our tutorial of Google Maps Nearby Places API is complete. You can see full code of MainActivity.java here:

Java
package com.androidtutorialpoint.googlemapsretrofit;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.androidtutorialpoint.googlemapsretrofit.POJO.Example;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import java.util.HashMap;

import retrofit.Call;
import retrofit.Callback;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    private GoogleMap mMap;
    double latitude;
    double longitude;
    private int PROXIMITY_RADIUS = 10000;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;
    LocationRequest mLocationRequest;

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

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkLocationPermission();
        }

        //show error dialog if Google Play Services not available
        if (!isGooglePlayServicesAvailable()) {
            Log.d("onCreate", "Google Play Services not available. Ending Test case.");
            finish();
        }
        else {
            Log.d("onCreate", "Google Play Services available. Continuing.");
        }

        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    private boolean isGooglePlayServicesAvailable() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(this);
        if(result != ConnectionResult.SUCCESS) {
            if(googleAPI.isUserResolvableError(result)) {
                googleAPI.getErrorDialog(this, result,
                        0).show();
            }
            return false;
        }
        return true;
    }

    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        //Initialize Google Play Services
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                buildGoogleApiClient();
                mMap.setMyLocationEnabled(true);
            }
        } else {
            buildGoogleApiClient();
            mMap.setMyLocationEnabled(true);
        }

        Button btnRestaurant = (Button) findViewById(R.id.btnRestaurant);
        btnRestaurant.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                build_retrofit_and_get_response("restaurant");
            }
        });

        Button btnHospital = (Button) findViewById(R.id.btnHospital);
        btnHospital.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                build_retrofit_and_get_response("hospital");
            }
        });

        Button btnSchool = (Button) findViewById(R.id.btnSchool);
        btnSchool.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                build_retrofit_and_get_response("school");
            }
        });
    }

    private void build_retrofit_and_get_response(String type) {

        String url = "https://maps.googleapis.com/maps/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        RetrofitMaps service = retrofit.create(RetrofitMaps.class);

        Call<Example> call = service.getNearbyPlaces(type, latitude + "," + longitude, PROXIMITY_RADIUS);

        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(Response<Example> response, Retrofit retrofit) {

                try {
                    mMap.clear();
                    // This loop will go through all the results and add marker on each location.
                    for (int i = 0; i < response.body().getResults().size(); i++) {
                        Double lat = response.body().getResults().get(i).getGeometry().getLocation().getLat();
                        Double lng = response.body().getResults().get(i).getGeometry().getLocation().getLng();
                        String placeName = response.body().getResults().get(i).getName();
                        String vicinity = response.body().getResults().get(i).getVicinity();
                        MarkerOptions markerOptions = new MarkerOptions();
                        LatLng latLng = new LatLng(lat, lng);
                        // Position of Marker on Map
                        markerOptions.position(latLng);
                        // Adding Title to the Marker
                        markerOptions.title(placeName + " : " + vicinity);
                        // Adding Marker to the Camera.
                        Marker m = mMap.addMarker(markerOptions);
                        // Adding colour to the marker
                        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                        // move map camera
                        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
                        mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
                    }
                } catch (Exception e) {
                    Log.d("onResponse", "There is an error");
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Throwable t) {
                Log.d("onFailure", t.toString());
            }
        });

    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onLocationChanged(Location location) {

        Log.d("onLocationChanged", "entered");

        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }
        //Place current location marker
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");

        // Adding colour to the marker
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));

        // Adding Marker to the Map
        mCurrLocationMarker = mMap.addMarker(markerOptions);

        //move map camera
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.animateCamera(CameraUpdateFactory.zoomTo(11));

        Log.d("onLocationChanged", String.format("latitude:%.3f longitude:%.3f", latitude, longitude));

        Log.d("onLocationChanged", "Exit");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    public boolean checkLocationPermission(){
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Asking user if explanation is needed
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

                //Prompt the user once explanation has been shown
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);


            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted. Do the
                    // contacts-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mMap.setMyLocationEnabled(true);
                    }

                } else {

                    // Permission denied, Disable the functionality that depends on this permission.
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }

            // other 'case' lines to check for other permissions this app might request.
            // You can add here other case statements according to your requirement.
        }
    }
}

We would suggest you to turn on GPS and Internet Connection. Run this Google Maps Nearby Places API on any real android device. It will first display your location. Now according to button clicked it will display nearby Restaurants, Schools or Hospitals as shown in following figure:

Google Maps Search Nearby

You can see demo of Google Maps Nearby Places API in the Youtube video given at the start of tutorial. We have tried to explain each and every step but still if you have any doubt then please comment. Also we are open to suggestions of any future tutorials. All the best 🙂 .

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Hello Developer!

As a co-founder, I would like to welcome you to the Android Tutorial Point community!. I hope you get the best possible value at of our platform. Stick with us for a while, and we promise you will become an $$Android Rockstar$$!

Android Tutorial Point is the right platform if you want to learn about android development. We have a broad collection of tutorials on different aspects of Android Development and it is growing rapidly. Here at Android Tutorial Point we thrive to deliver the best tutorials. In this direction, we are trying to create a community that will cater to your needs, whether you are a beginner or a seasoned veteran. For the beginners that are getting started on Android Development
journey, we would suggest you to begin with our Android Basics Tutorial available at http://www.androidtutorialpoint.com/category/basics/ . Here, we feature articles on how to start with Android programming.


All the best from the Android Tutorial Point team. Don't forget to subscribe our blog for latest android tutorials. You can reach out to us at our Facebook page https://www.facebook.com/androidtutorialpoint/ or Add us on Twitter https://twitter.com/androidtutpoint/ . Any ideas or suggestions? Shoot us an email at androidtutorialspoint@gmail.com

Comments and Discussions

 
Questionerror Pin
Member 1483578418-May-20 0:05
Member 1483578418-May-20 0:05 
QuestionNot Getting Json responce Properly Pin
Wakimul Alam12-Apr-17 6:55
Wakimul Alam12-Apr-17 6:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.