Android Google Places API Example

In this post, I will work with Google’s popular Google Places API. This API provides us nearby places according to our search and provides us with places which are nearby and according to the name searched by the user.

There are two ways to do this:-

  1. Using Google Places Web Service that I will show u in this tutorial.
  2. Using Google Places API with Google Client about which I will describe in next tutorials.

Google places provide places information such as establishments, geographic locations, places name, places address and much more.For official information visit here.

So, Lets Start

1.In order to use Google Places API first, we need a key and enabled Google Places API.Create a key here.

2. We need to add Internet Permission in applications AndroidManifest file.

<uses-permission android:name="android.permission.INTERNET"/>

3.To implement Google places we need:-

  1. MainActivity as activity class containing AutoCompleteTextView to show google places.
  2. Adapter class implementing the Filterable interface to show google places and then set to AutoCompleteTextView.
  3. Model Class to contain google places object.

4.Open Eclipse or Android Studio -> New Project->Android Application Project-> Name of Application-> Follow all instructions and complete by clicking on Finish.

5.Now i will create Model class as MyGooglePlaces and add getters, setters to it.

MyGooglePlaces.java

package com.coderzpassion.googleplacessample;

/**
 * Created by coderzpassion on 04/03/16.
 */
public class MyGooglePlaces {
    private String name;
    private String category;
    private String rating;
    private String opennow;
    private String vicinity;
    private double latitude,longitude;

    public MyGooglePlaces()
    {
        this.name="";
        this.category="";
        this.rating="";
        this.opennow="";
        this.vicinity="";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getRating() {
        return rating;
    }

    public void setRating(String rating) {
        this.rating = rating;
    }

    public String getOpen() {
        return opennow;
    }

    public void setOpenNow(String open) {
        this.opennow = open;
    }

    public String getVicinity() {
        return vicinity;
    }

    public void setVicinity(String vicinity) {
        this.vicinity = vicinity;
    }

    public void setLatLng(double lat,double lon)
    {
        this.latitude=lat;
        this.longitude=lon;
    }
}

6. Now i will create a layout for adapter as autocomplete.xml

autocomplete.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/myplaces"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

7. Now i will create Adapter class implementing Filterable interface to filter results.

MyPlacesAdapter.java

package com.coderzpassion.googleplacessample;

import android.content.Context;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

/**
 * Created by coderzpassion on 05/03/16.
 */
public class MyPlacesAdapter extends BaseAdapter implements Filterable {

    private LayoutInflater mInflater;
    Context con;
 ArrayList<MyGooglePlaces> places=new ArrayList<MyGooglePlaces>();

    public MyPlacesAdapter(Context context) {
        super();
        mInflater = LayoutInflater.from(context);
        con=context;
    }

    // get total count of array
    @Override
    public int getCount() {
        return places.size();
    }

    //get item id
    @Override
    public long getItemId(int position) {
        return position;
    }

    // get Mygoogleplaces object at given position
    @Override
    public MyGooglePlaces getItem(int position) {
        return places.get(position);
    }

    //Filter to filter the results
    @Override
    public Filter getFilter() {
        Filter filter=new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
               FilterResults results=new FilterResults();
                if(constraint!=null)
                {
                  places=getPredictions(constraint.toString());
                    if(places!=null)
                    {
                        results.values=places;
                        results.count=places.size();
                    }
                }
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results != null && results.count > 0) {
                    // The API returned at least one result, update the data.
                    notifyDataSetChanged();
                } else {
                    // The API did not return any results, invalidate the data set.
                    notifyDataSetInvalidated();
                }
            }
        };
        return filter;
    }

    // method to get different places nearby search location
    private ArrayList<MyGooglePlaces> getPredictions(String constraint)
    {
        //pass your current latitude and longitude to find nearby and ranky=distance means places will be found in ascending order
        // according to distance
        double latitude=30.7333;
        double longitude=76.7794;
        String API_KEY="AIzaSyByodZEsDBTC-J3brJ39JiYTkqbtJhlSKo";
      String url= "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="+latitude+","+longitude+"&rankby=distance&name="+constraint+"&key="+API_KEY;
          return getPlaces(url);
    }

    private ArrayList<MyGooglePlaces> getPlaces(String constraint)
    {
        //code for API level 23 as httpclient is depricated in API 23
        StringBuffer sb=null;
        URL url;
        HttpURLConnection urlConnection = null;
        try {
            url = new URL(constraint);

            urlConnection = (HttpURLConnection) url.openConnection();
            InputStream in = urlConnection.getInputStream();
            InputStreamReader isw = new InputStreamReader(in);
            int data = isw.read();
             sb=new StringBuffer("");
            while (data != -1) {
                sb.append((char)data);
                //char current = (char) data;
                data = isw.read();
               // System.out.print(current);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
      return   parseGoogleParse(sb.toString());
    }


// method to parse the json returned by googleplaces api
    private static ArrayList parseGoogleParse(final String response) {

        ArrayList<MyGooglePlaces> temp = new ArrayList();

        try {

            // make an jsonObject in order to parse the response
            JSONObject jsonObject = new JSONObject(response);
            // make an jsonObject in order to parse the response

            if (jsonObject.has("results")) {

                JSONArray jsonArray = jsonObject.getJSONArray("results");

                for (int i = 0; i < jsonArray.length(); i++) {

                    MyGooglePlaces poi = new MyGooglePlaces();

                    if (jsonArray.getJSONObject(i).has("name")) {

                        poi.setName(jsonArray.getJSONObject(i).optString("name"));
                        poi.setRating(jsonArray.getJSONObject(i).optString("rating", " "));

                        if (jsonArray.getJSONObject(i).has("opening_hours")) {

                            if (jsonArray.getJSONObject(i).getJSONObject("opening_hours").has("open_now")) {
                                if (jsonArray.getJSONObject(i).getJSONObject("opening_hours").getString("open_now").equals("true")) {
                                    poi.setOpenNow("YES");

                                } else {
                                    poi.setOpenNow("NO");
                                }
                            }
                        } else {
                            poi.setOpenNow("Not Known");
                        }

                        if (jsonArray.getJSONObject(i).has("geometry"))
                        {
                            if (jsonArray.getJSONObject(i).getJSONObject("geometry").has("location"))
                            {
                                if (jsonArray.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").has("lat"))
                                {
                                    poi.setLatLng(Double.parseDouble(jsonArray.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getString("lat")), Double.parseDouble(jsonArray.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getString("lng")));

                                }
                            }
                        }
                        if (jsonArray.getJSONObject(i).has("vicinity")) {

                            poi.setVicinity(jsonArray.getJSONObject(i).optString("vicinity"));
                        }
                        if (jsonArray.getJSONObject(i).has("types")) {

                            JSONArray typesArray = jsonArray.getJSONObject(i).getJSONArray("types");

                            for (int j = 0; j < typesArray.length(); j++) {
                                poi.setCategory(typesArray.getString(j) + ", " + poi.getCategory());
                            }
                        }
                    }
                    //if(temp.size()<5)
                        temp.add(poi);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList();
        }

        return temp;

    }

    // View method called for each row of the result
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid unnecessary calls
        // to findViewById() on each row.
        ViewHolder holder;

        // When convertView is not null, we can reuse it directly, there is no need
        // to reinflate it. We only inflate a new View when the convertView supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.autocomplete, null);

            // Creates a ViewHolder and store references to the two children views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.myplaces);
            holder.address=(TextView)convertView.findViewById(R.id.address);
            // Bind the data efficiently with the holder.

            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }

        // If weren't re-ordering this you could rely on what you set last time
        holder.text.setText(Html.fromHtml("<b>"+places.get(position).getName()+"<b>"));
        holder.address.setText(places.get(position).getVicinity());

        return convertView;
    }

  // viewholder class to hold adapter views
    static class ViewHolder {
        TextView text,address;
    }
}

8. Now i will create a layout for MainActivity.java that will be our mainscreen of the application containing autocompletetextview.

activity_main.xml

<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="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:text="Search Places"
        android:layout_margin="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <AutoCompleteTextView
        android:id="@+id/places"
        android:layout_margin="10dp"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

9. Now i will code for MainActivity.java setting adapter to autocompletetextview and handling click for it.

MainActivity.java

package com.coderzpassion.googleplacessample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;

public class MainActivity extends AppCompatActivity {

    AutoCompleteTextView places;
    MyPlacesAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        places=(AutoCompleteTextView)findViewById(R.id.places);
        adapter=new MyPlacesAdapter(MainActivity.this);
        places.setAdapter(adapter);
// text changed listener to get results precisely according to our search
        places.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
//calling getfilter to filter the results
                adapter.getFilter().filter(s);
//notify the adapters after results changed
                adapter.notifyDataSetChanged();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

// handling click of autotextcompleteview items
        places.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                MyGooglePlaces googlePlaces=(MyGooglePlaces)parent.getItemAtPosition(position);
                places.setText(googlePlaces.getName());

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Output

androidhowtousegoogleplacesapi            androidworkingwithgoogleplaces