--

Thursday 16 February 2017

Showing nearby places on Google Map using Places API


Google Places API gives us the full access to the Google database around 100 billion places around the world. The Places API retrieves rich details about a place, including name, address, phone number, website link and more. I have developed an application which fetches nearby places from Places API then mark those places on Google Map.




Step 1: Generating Google API Key

If you have to use Places API, we should create API key along with specific package name by going to Google Places APIs console.  

Step 2: Adding play services in build.gradle

compile 'com.google.android.gms:play-services:8.3.0'

Step 3: Adding permission in manifest

<uses-permission android:name="android.permission.INTERNET" />
<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"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.google.android.gms.location.sample.geofencing.permission.MAPS_RECEIVE" />
We have to specify the API key in meta-data.
<meta-data    android:name="com.google.android.maps.v2.API_KEY"    android:value="AIzaSyAOLfVEAzUpcaQ0zTDuhCsrMk9ZDuyr5lw" />

Step 4:  Initializing Google API client

Building GoogleAPIClient for adding LocationServices API then creating LocationRequest for fetching user location at specified time interval.
mGoogleApiClient = new GoogleApiClient.Builder(ctx)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .addApi(LocationServices.API).build();
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
         .setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setExpirationDuration(EXPIRE_INTERVAL_IN_MILLISECONDS);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build(); 
By implementing LocationListener, we get current latitude and longitude from last known location in the onLocationChanged override method.
@Overridepublic void onLocationChanged(Location location) {

    mLastLocation=location;

    latitude = String.valueOf(mLastLocation.getLatitude());
    longitude = String.valueOf(mLastLocation.getLongitude());
}

Step 5: Calling Places API service

PROXIMITY_RADIUS=2000;
String GOOGLE_API_KEY=getResources().getString(R.string.google_places_api_key);

StringBuilder googlePlacesUrl = new StringBuilder("https://maps." +
        "googleapis.com/maps/api/place/nearbysearch/json?");
googlePlacesUrl.append("location=" + latitude + "," + longitude);
googlePlacesUrl.append("&radius=" + PROXIMITY_RADIUS);
googlePlacesUrl.append("&types=" + TYPES);
googlePlacesUrl.append("&sensor=true");
googlePlacesUrl.append("&hasNextPage=true");
googlePlacesUrl.append("&nextPage()=true");
googlePlacesUrl.append("&key=" + GOOGLE_API_KEY);

String strPlacesUrl=googlePlacesUrl.toString();
Log.d(TAG, "getGooglePlacesData-URL:" + strPlacesUrl);
GooglePlacesReadTask googlePlacesReadTask = new GooglePlacesReadTask(ctx);
Object[] toPass = new Object[1];
toPass[0] = strPlacesUrl;
googlePlacesReadTask.execute(toPass);
We should specify the radius from the current location to fetch nearby places.  The type of places to Places API is segregated into FOOD, BANK, ENTERTAINMENT, SHOPPING, TRANSPORT, HEALTH, and PEACE.
public static final String TYPE_FOOD="restaurant|food|bar|" +
        "cafe|bakery|meal_takeaway|lodging";

public static final String TYPE_BANK="bank|atm|accounting|" +
        "courthouse|embassy|insurance_agency|local_government_office" +
        "|police|post_office|school|university";

public static final String TYPE_ENTERTAIN="amusement_park|aquarium|" +
        "art_gallery|casino|city_hall|movie_rental|movie_theater|" +
        "museum|night_club|park|stadium|zoo|bowling_alley|library";

public static final String TYPE_SHOPPING="bicycle_store|book_store" +
        "|clothing_store|convenience_store|department_store|electronics_store" +
        "|furniture_store|hardware_store|home_goods_store|jewelry_store|" +
        "liquor_store|pet_store|shoe_store|shopping_mall";

public static final String TYPE_TRANSPORT="airport|bus_station|car_dealer" +
        "|car_rental|car_repair|car_wash|fire_station|gas_station|subway_station" +
        "|taxi_stand|train_station|transit_station|travel_agency";

public static final String TYPE_HEALTH="beauty_salon|campground|dentist|doctor" +
        "|florist|gym|hair_care|hospital|laundry|pharmacy|physiotherapist|spa" +
        "|veterinary_care";

public static final String TYPE_PEACE="cemetery|church|hindu_temple|mosque|synagogue";


We use an AsyncTask to run the places API request in the background thread. It runs in a separate thread and requests the Google server for the Google Places information. The HttpURLConnection library access Places API and returns the rich detailed information about nearby places based on given type of the place.
public String read(String httpUrl) throws IOException {
    String httpData = "";
    InputStream inputStream = null;
    HttpURLConnection httpURLConnection = null;
    try {
        URL url = new URL(httpUrl);
        httpURLConnection = (HttpURLConnection) url.openConnection();
        httpURLConnection.connect();
        inputStream = httpURLConnection.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new                InputStreamReader(inputStream));
        StringBuffer stringBuffer = new StringBuffer();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            stringBuffer.append(line);
        }
        httpData = stringBuffer.toString();
        bufferedReader.close();
    } catch (Exception e) {
        Log.d("Googleplaces", "Exception - reading Http url" + e.toString());
    } finally {
        inputStream.close();
        httpURLConnection.disconnect();
    }
    return httpData;
}

Step 6: Showing places on Google Map

Adding supportMapFragment in the XML layout and initialize it in onCreate(). 
<fragment
    android:id="@+id/googleMap"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.SupportMapFragment"
    android:layout_alignParentTop="true"
    android:layout_toEndOf="@+id/layout_latlongLocation" />
SupportMapFragment supportMapFragment =
        (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.googleMap);
googleMap = supportMapFragment.getMap();
googleMap.setMyLocationEnabled(true);
We should parse the API response and fetch required information like place name, latitude, longitude that used to mark the place on Google Map.
MarkerOptions new_marker = new MarkerOptions();
new_marker.position(loc).title(placeName);
new_marker.icon(icon);
googleMap.addMarker(new_marker);
 

 Step 7: Obtaining more than 20 places from API response

The places API response always returns only 20 places around you. If you need to obtain more than 20, you should append nextPage() & hasNextPage in Places API request.
googlePlacesUrl.append("&hasNextPage=true");
googlePlacesUrl.append("&nextPage()=true");
We obtain the next_page_token from API response at first time. Next, we should add page token to API request to get next set of 20 places so we can fetch up to 60 places likewise.
StringBuilder googlePlacesUrl = new StringBuilder("https://maps.googleapis.com" +
        "/maps/api/place/nearbysearch/json?"); // working
googlePlacesUrl.append("location=" + latitude + "," + longitude);
googlePlacesUrl.append("&radius=" + PROXIMITY_RADIUS);
googlePlacesUrl.append("&types=" + String.valueOf(selectedType));
googlePlacesUrl.append("&sensor=true");
googlePlacesUrl.append("&hasNextPage=true");
googlePlacesUrl.append("&nextPage()=true");
googlePlacesUrl.append("&key=" + GOOGLE_API_KEY);
googlePlacesUrl.append("&pagetoken=" + NEXT_PAGE_TOKEN);
The parsing response and marking on Google map is same as first time. I have uploaded latest source code in GitHub for your reference.
https://github.com/JayaprakashR-Zealot/Knowledge-Circle---Android/tree/master/NearByPlaces 

Kindly raise your queries in the command section.

Happy coding!!!
Cheers!!!