Skip to main content

Android: Place Search using Google Places API

The Google Places API allows you to query for place information on a variety of categories, such as: establishments, prominent points of interest, geographic locations, and much more. You can search for places either by proximity or a text string. A Place Search returns a list of Places along with summary information about each Place; If you want to view additional information it is extracted using Place Details query.

An HTTP URL is used for search query specifying the type of Place you are searching, latitude and longitude of your location and radius.The HTTP URL should look like:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=YourAPIKey

Mandatory parameters
key — Your application's API key. This key identifies your application for purposes of quota management and so that Places added from your application are made immediately available to your app. Visit the APIs Console to create an API Project and obtain your key.
location — The latitude/longitude around which to retrieve Place information. This must be specified as latitude,longitude.
radius — Defines the distance (in meters) within which to return Place results. The maximum allowed radius is 50 000 meters. Note that radius must not be included if rankby=distance (described under Optional parameters below) is specified.
sensor — Indicates whether or not the Place request came from a device using a location sensor (e.g. a GPS) to determine the location sent in this request. This value must be either true or false.

A JSON response contains up to four root elements:
status: contains metadata on the request. See Status Codes below.
results: contains an array of Places, with information about each. See Nearby Search Results for information about these results. The Places API returns up to 20 establishment results per query. Additionally, political results may be returned which serve to identify the area of the request.
html_attributions: contain a set of attributions about this listing which must be displayed to the user.
next_page_token: contains a token that can be used to return up to 20 additional results. A next_page_token will not be returned if there are no additional results to display. The maximum number of results that can be returned is 60. There is a short delay between when a next_page_token is issued, and when it will become valid.

Status Codes
The status field within the search response object contains the status of the request, and may contain debugging information to help you track down why the request failed. The status field may contain the following values:
OK indicates that no errors occurred; the place was successfully detected and at least one result was returned.
ZERO_RESULTS indicates that the search was successful but returned no results. This may occur if the search was passed a latlng in a remote location.
OVER_QUERY_LIMIT indicates that you are over your quota.
REQUEST_DENIED indicates that your request was denied, generally because of lack of a sensor parameter.
INVALID_REQUEST generally indicates that a required query parameter (location or radius) is missing.

Place Detail Search
Once you have a reference from a Place Search, you can request more details about a particular establishment or point of interest by initiating a Place Details request. A Place Details request returns more comprehensive information about the indicated place such as its complete address, phone number, user rating and reviews.
A Place Details request is an HTTP URL of the following form: https://maps.googleapis.com/maps/api/place/details/json?reference=ReferenceToPlace& sensor=true&key=AddYourOwnKeyHere
Adding Your Own new Place using Google Places API
Using Google Places API one can add their own new place to map for which the HTTP URL should look like:
POST https://maps.googleapis.com/maps/api/place/add/json?sensor=true_or_false&key=AddYourOwnKeyHere HTTP/1.1
Host: maps.googleapis.com{
"location": {
"lat": -33.8669710,
"lng": 151.1958750
},
"accuracy": 50,
"name": "Google Shoes!",
"types": ["shoe_store"],
"language": "en-AU"
}

Deleting a Place
A Place can only be deleted if:
It was added by the same application as is requesting its deletion.
It has not successfully passed through the Google Maps moderation process, and and is therefore not visible to all applications.
Attempting to delete a Place that does not meet these criteria will return a REQUEST_DENIED status code.
A Place Report delete request is an HTTP POST request of the following form:
POST https://maps.googleapis.com/maps/api/place/delete/json?sensor=true_or_false
&key=AddYourOwnKeyHere HTTP/1.1 Host: maps.googleapis.com { "reference": "place_reference" }

Complete Source Code:

PlaceRequest.Java
This class have place search, search place details, add new place and delete place
methods.
Note: Use Own valid Key in API_KEY = "YourMapKeyHere" and any
where else needed.

public class PlaceRequest {

 // ArraList to store corresponding lat, lng
 static List<Double> latList = new ArrayList<Double>();
 static List<Double> lngList = new ArrayList<Double>();

 // Create our transport.
 private static final HttpTransport transport = new ApacheHttpTransport();
 // The different Places API endpoints.
 // order of data in requested URL doesn'n matter
 private static final String PLACES_SEARCH_URL = 
   "https://maps.googleapis.com/maps/api/place/search/json?";
 private static final String PLACES_DETAILS_URL =
   "https://maps.googleapis.com/maps/api/place/details/json?";
 private static final String PLACE_ADD_URL =
   "https://maps.googleapis.com/maps/api/place/add/json?" +
   "key=AIzaSyAnOvJ-Woki5W5jUiZhv5bJ5YGB6ZY3yrs&sensor=false";
 private static final String PLACES_DELETE_URL =
   "https://maps.googleapis.com/maps/api/place/delete/json?" +
   "key=AIzaSyAnOvJ-Woki5W5jUiZhv5bJ5YGB6ZY3yrs&sensor=false";


 // Fill in the API key you want to use.
 private static final String API_KEY = "YourMapKeyHere";
 static final String LOG_KEY = "GooglePlace";

 static ArrayList<String> placeReference =  new ArrayList<String>();
  
 private static String mySearchType = "hospital";  // this is just for testing
 private static String searchName = "OffCourse Golf Hole";
   
 // converting back to -33.8670522, 151.1957362 format
 double latitude = ShowGoogleMap.updated_lat / 1E6;
 double longitude = ShowGoogleMap.updated_lng / 1E6;

 // Sydney, Australia
 //double latitude = -33.8670522;
 //double longitude = 151.1957362;

 // telenet
 //double latitude = 51.034823;
 //double longitude = 4.483774;

 public PlacesList performSearch() throws Exception {
  try {
   Log.v(LOG_KEY, "Start Search...");
   GenericUrl reqUrl = new GenericUrl(PLACES_SEARCH_URL);
   reqUrl.put("key", API_KEY);
   reqUrl.put("location", latitude + "," + longitude);
   reqUrl.put("radius", 5000); // radius of 5Km
   reqUrl.put("types", mySearchType);
   reqUrl.put("name", searchName);
   reqUrl.put("sensor", "false");
   Log.v(LOG_KEY, "Requested URL= " + reqUrl);
   HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
   HttpRequest request = httpRequestFactory.buildGetRequest(reqUrl);
   
    Log.v(LOG_KEY, request.execute().parseAsString());      
    PlacesList places = request.execute().parseAs(PlacesList.class);
    Log.v(LOG_KEY, "STATUS = " + places.status);
    // empty array lists
    latList.clear();
    lngList.clear();
    for (Place place : places.results) {
     Log.v(LOG_KEY, place.name);
     latList.add(place.geometry.location.lat);
     lngList.add(place.geometry.location.lng);
     // assign last added place reference
     placeReference.add(place.reference);
    
    }         
    return places;

  } catch (HttpResponseException e) {
   Log.v(LOG_KEY, e.getResponse().parseAsString());
   throw e;
  }
 
  catch (IOException e) {
   // TODO: handle exception
   throw e;
  }
 }

 public PlaceDetail performDetails(String reference) throws Exception {
  try {
   Log.v(LOG_KEY, "Perform Place Detail....");
   GenericUrl reqUrl = new GenericUrl(PLACES_DETAILS_URL);
   reqUrl.put("key", API_KEY);
   reqUrl.put("reference", reference);
   reqUrl.put("sensor", "false");
   Log.v(LOG_KEY, "Requested URL= " + reqUrl);
   HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
   HttpRequest request = httpRequestFactory.buildGetRequest(reqUrl);

   Log.v(LOG_KEY, request.execute().parseAsString());
   PlaceDetail placeDetail = request.execute().parseAs(PlaceDetail.class);
  
   return placeDetail;
      
  } catch (HttpResponseException e) {
   Log.v(LOG_KEY, e.getResponse().parseAsString());
   throw e;
  }
  catch (IOException e) {
   // TODO: handle exception
   throw e;
  }
  
 }

 public JSONObject addPlace(double lat, double lng, String type, String name) throws Exception {
  try {
   Log.v(LOG_KEY, "Adding Place...");
    String vic = "5/48 Pirrama Road, Pyrmont";
    String formtd_address = "5/48 Pirrama Road, Pyrmont NSW, Australia";
    String formtd_phone_number = "(02) 9374 4000";
    String myUrl = "http://maps.google.com/maps/place?cid=10281119596374313554";
    String myWebsite = "http://www.google.com.au/";
   
   HttpPost post = new HttpPost(PLACE_ADD_URL);
   String postBody =
      "{"+
               "\"location\": {" +
                 "\"lat\": " + lat + "," +
                 "\"lng\": " + lng +
                "}," +
                "\"accuracy\":50.0," +
                "\"name\": \"" + name + "\"," +
                "\"types\": [\"" + type + "\"]," +
                "\"vicinity\":\""+ PlaceAdd.vic +"\","+
                "\"formatted_address\":\""+ PlaceAdd.formtd_address +"\","+
                "\"formatted_phone_number\":\""+ PlaceAdd.formtd_phone_number +"\","+
                "\"url\":\""+ PlaceAdd.myUrl +"\","+
                "\"website\":\""+ PlaceAdd.myWebsite +"\","+ 
                "\"language\": \"en\" " +
               
           "}";
  
   StringEntity se = new StringEntity(postBody,HTTP.UTF_8);
   post.setEntity(se);
   ResponseHandler<String> responseHandler=new BasicResponseHandler();
   String responseBody = new DefaultHttpClient().execute(post, responseHandler);
   JSONObject response = new JSONObject(responseBody);
   Log.v(LOG_KEY, "Requested URL= " + PLACE_ADD_URL);
       
   return response;

  } catch (HttpResponseException e) {
   Log.v(LOG_KEY, e.getResponse().parseAsString());
   throw e;
  }
 
  catch (IOException e) {
   // TODO: handle exception
   throw e;
  }
 } 

 public JSONObject deletePlace(String reference) throws Exception {
  try {
   Log.v(LOG_KEY, "Deleting Place...");
   HttpPost post = new HttpPost(PLACES_DELETE_URL);  
   String postBody = "{\"reference\":\""+ reference +"\"}";
   StringEntity se = new StringEntity(postBody,HTTP.UTF_8);
   post.setEntity(se);
   ResponseHandler<String> responseHandler = new BasicResponseHandler();
   String responseBody = new DefaultHttpClient().execute(post, responseHandler);
   JSONObject response = new JSONObject(responseBody);
   Log.v(LOG_KEY, "Requested URL= " + PLACES_DELETE_URL);
       
   return response;
      
  } catch (HttpResponseException e) {
   Log.v(LOG_KEY, e.getResponse().parseAsString());
   throw e;
  }
  catch (IOException e) {
   // TODO: handle exception
   throw e;
  }
  
 }

 public static HttpRequestFactory createRequestFactory(final HttpTransport transport) {
     
    return transport.createRequestFactory(new HttpRequestInitializer() {
     public void initialize(HttpRequest request) {
      GoogleHeaders headers = new GoogleHeaders();
      headers.setApplicationName("Google-Places-DemoApp");
      request.setHeaders(headers);
      JsonHttpParser parser = new JsonHttpParser(new JacksonFactory()) ;
      //JsonHttpParser.builder(new JacksonFactory());
      //parser.jsonFactory = new JacksonFactory();
      request.addParser(parser);
     }
  });
 }

}
Now call PlaceRequest.java from PlaceAdd.java to add you actual location into Google Map.
PlaceAdd.java
public class PlaceAdd extends Activity{

 static String placeName;
 static String vic;
 static String formtd_address;
 static String formtd_phone_number;
 static String myUrl;
 static String myWebsite;

 ProgressDialog progressDialog;

 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
      //set up dialog
      Dialog dialog = new Dialog(this);
      dialog.setContentView(R.layout.addplace);
      dialog.setTitle("Enter Place Details");
      dialog.setCancelable(false);
     
      final EditText name = (EditText) dialog.findViewById(R.id.place_title);
      final EditText vicinity = (EditText) dialog.findViewById(R.id.editText1);
      final EditText formatted_address = (EditText) dialog.findViewById(R.id.editText2);
      final EditText formatted_phone_number = (EditText) dialog.findViewById(R.id.editText3);
      final EditText url = (EditText) dialog.findViewById(R.id.editText4);
      final EditText website = (EditText) dialog.findViewById(R.id.editText5);
    
   
    
      Button ok = (Button) dialog.findViewById(R.id.btn_ok);
      ok.setOnClickListener(new OnClickListener() {
          public void onClick(View v) {
           placeName = name.getText().toString();
           vic = vicinity.getText().toString();
              formtd_address = formatted_address.getText().toString();
              formtd_phone_number = formatted_phone_number.getText().toString();
              myUrl =  url.getText().toString();
              myWebsite = website.getText().toString();
             
           Log.v(PlaceRequest.LOG_KEY, "Description: " + vic);
           Log.v(PlaceRequest.LOG_KEY, "Description: " + formtd_address);
           Log.v(PlaceRequest.LOG_KEY, "Description: " + formtd_phone_number);
           Log.v(PlaceRequest.LOG_KEY, "Description: " + myUrl);
           Log.v(PlaceRequest.LOG_KEY, "Description: " + myWebsite);
          
           AddSrv srv = new AddSrv();  
    //setProgressBarIndeterminateVisibility(true);
    srv.execute();
    //YouTube.this.getApplicationContext()
    progressDialog = ProgressDialog.show(PlaceAdd.this, "",  "Adding Place! Please wait...", true);
           
          }
      });
    
      Button cancel = (Button) dialog.findViewById(R.id.btn_cancel);
      cancel.setOnClickListener(new OnClickListener() {
          public void onClick(View v) {
          Toast.makeText(getBaseContext(), "Adding Place is cancelled!",
            Toast.LENGTH_SHORT).show();
           finish();
          }
      });
       //now that the dialog is set up, it's time to show it   
       dialog.show();
    
 }
 class AddSrv extends AsyncTask<Void, Void, JSONObject>{
     @Override
     protected JSONObject doInBackground(Void... params) {
      JSONObject pl = null;
      try {
       // send place search request from here
        pl =   new PlaceRequest().addPlace(ShowGoogleMap.addLat,
          ShowGoogleMap.addLng, ShowGoogleMap.locType, placeName); 
      } catch (Exception e) {
       e.printStackTrace();
      }
      return pl;
     }
    
     @Override
     protected void onPostExecute(JSONObject result) {           
   Log.v(PlaceRequest.LOG_KEY, "Place Added is: " + result);
  
  
   if (result != null){
     Toast.makeText(getBaseContext(), "Your Place is added",
       Toast.LENGTH_SHORT).show();
   }
   else{
    Toast.makeText(getBaseContext(), "Please Try Again",
      Toast.LENGTH_SHORT).show();
   }
   //setProgressBarIndeterminateVisibility(false);
   progressDialog.dismiss();
   finish();
     }
    } // End of class SearchSrv here  
}
Now call PlaceRequest.java from ShowPlaceDetail.java to view Place detail.
public class ShowPlaceDetail extends Activity {
  ProgressDialog progressDialog;
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
                 //set up dialog
                 Dialog dialog = new Dialog(ShowPlaceDetail.this);
                 dialog.setContentView(R.layout.maindialog);
                 dialog.setTitle(MyItemizedOverlay.title);
                 dialog.setCancelable(false);
 
                 //set up text
                 TextView text = (TextView) dialog.findViewById(R.id.TextView01);
                 text.setText(ShowGoogleMap.detailText);
 
                 //set up image view
                 ImageView img = (ImageView) dialog.findViewById(R.id.ImageView01);
                 img.setImageResource(R.drawable.user_marker);
 
                 //set up button
                 Button button = (Button) dialog.findViewById(R.id.cancel_button);
                 button.setOnClickListener(new OnClickListener() {
                     public void onClick(View v) {
                      ShowPlaceDetail.this.finish();
                     }
                 });
                
                 Button deletButton = (Button) dialog.findViewById(R.id.delete);
                 deletButton.setOnClickListener(new OnClickListener() {
                     public void onClick(View v) {
                      DelSrv srv = new DelSrv();   
             //setProgressBarIndeterminateVisibility(true);
             srv.execute();
             progressDialog = ProgressDialog.show(ShowPlaceDetail.this, "",

                         "Deleting! Please wait...", true);
                     }
                 });
                
                 Button photoButton = (Button) dialog.findViewById(R.id.photo);
                 photoButton.setOnClickListener(new OnClickListener() {
                     public void onClick(View v) {
                      finish();
                     }
                 });
                 //now that the dialog is set up, it's time to show it   
                 dialog.show();
             }
    
      private class DelSrv extends AsyncTask<Void, Void, JSONObject>{
      @Override
      protected JSONObject doInBackground(Void... params) {
       JSONObject pl = null;
       try {
        // send place search request from here
         pl =   new PlaceRequest().deletePlace(MyItemizedOverlay.reference); 
       } catch (Exception e) {
        e.printStackTrace();
       }
       return pl;
      }
      @Override
      protected void onPostExecute(JSONObject result) {            
    Log.v(PlaceRequest.LOG_KEY, "Place Deleted is: " + result);
   
    if (result != null){
      Toast.makeText(getBaseContext(), "Your Place is Deleted",

                    Toast.LENGTH_SHORT).show();
    }
    else{
     Toast.makeText(getBaseContext(), "Please Try Again",

           Toast.LENGTH_SHORT).show();
    }
    //setProgressBarIndeterminateVisibility(false);
    progressDialog.dismiss();
    finish();
      }
     } // End of class SearchSrv here
  }
All Bean classes for Search Place, Add Place and Place details look like:
public class Place {
 @Key
 public String id;

 @Key
 public String name;

 @Key
 public String reference;

 @Key
 public String types[];

 @Key
 public String international_phone_number;

 @Key
 public String vicinity;

 @Key
 public String formatted_address;

 @Key
 public String url;

 @Key
 public String rating;

 @Key
 public String website;

 @Key
 public List<Place> address_components;

 @Key
 public String long_name;

 @Key
 public String short_name;
   
 @Key
 public PlaceGeometry geometry;

 public static class PlaceGeometry {
  @Key
  public Location location;
 }

 public static class Location {
  @Key
  public double lat;

  @Key
  public double lng;
 }

 @Override
 public String toString() {
  return name + " - " + id + " - " + reference;
 }
}
public class PlaceDetail {

 @Key
 public Place result;

 @Override
 public String toString() {
  if (result!=null) {
   return result.toString();
  }
  return super.toString();
 }
}
public class PlaceAutoComplete {

 @Key
 public String id;

 @Key
 public String description;

 @Key
 public String reference;


 @Override
 public String toString() {
  return description + " - " + id + " - " + reference;
 }
 }
public class PlacesList {
 @Key
 public String status;
 @Key
 public List<Place> results;
}



Place Search and Add Place Screen shot look like:



Comments

Popular posts from this blog

Fragment: App loads with white screen for 3 secs before showing proper UI

Issue: 1) When my application start then white/black screen appears, and then main UI is display.  2) Before my fragment load in activity black/white screen appears for 3/4 seconds and then fragment load. Solution: To fix this nasty problem, update the /res/values/styles.xml to include <item name="android:windowDisablePreview">true</item> or <item name="android:windowBackground">@android:color/black</item> for example : <!-- Application theme. -->  <style name="AppTheme" parent="AppBaseTheme">  <!-- All customizations that are NOT specific to a particular API-level can go here. -->  <item name="android:windowDisablePreview">true</item>  <!-- <item name="android:windowBackground">@android:color/black</item> -->  </style>

Android: The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files

Solution Try the following any one solution and problem will go away: 1)  Apply following steps: Close the project and reopen it. Clean the project (It will rebuild the buildpath hence reconfiguring with the JDK libraries) OR Delete and Re-import the project and if necessary do the above steps again. 2)  Apply following steps: Go to properties of project with the build error (right click > Properties) View the "Libraries" tab in the "Build Path" section Find the "JRE System Library" in the list (if this is missing then this error message is not an eclipse bug but a mis-configured project) Remove the "JRE System Library" Hit "Add Library ...", Select "JRE System Library" and add the appropriate JRE for the project (eg. 'Workspace default JRE') Hit "Finish" in the library selection and "OK" in the project properties and then wait for the re-build of the project Hopefully th

Error: Retrieving parent for item: No resource found that matches the given name after upgrading to AppCompat v23

My project is going on easily but suddenly what I found below bugs when developing an app. I know it's minor bug but it may be useful to anyone. Here is the error: Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'. Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'. Solution: This happens because after updates your android studio uses API 23 by default. 1) First check that your compile SDK version must match the support library's major version. If you are using version 23 of the support library, you need to compile against version 23 of the Android SDK. Alternatively you can continue compiling against version 22 of the Android SDK by switching to the latest support library v22.   2) Go to your project structure -> Properties -> and change Build tool version to