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:-
- Using Google Places Web Service that I will show u in this tutorial.
- 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:-
- MainActivity as activity class containing AutoCompleteTextView to show google places.
- Adapter class implementing the Filterable interface to show google places and then set to AutoCompleteTextView.
- 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