URL class rendering - Invalid_Request with next_page_token - android

In my Android application the user can select categories (cafe, restaurant, ...) of which places he wants to see.
I get result from the google-places-api with a next_page_token, when I use the following url:
https://maps.googleapis.com/maps/api/place/textsearch/json?query=cafe+in+Elfde-Liniestraat%2C+Hasselt%2C+Belgium&pagetoken=ClRHAAAAqYa7IpwMQH3q1DyinfsMnkuOaZg8wQrp0pvzarv13pwqruqT2YfaEry6v_d-L4d_TC13G6iHuPz-rc1KbI6XRE01rB5CuXcHISu-CI_CaKESEMUxSjHhHDNee4xbr2tPEZcaFPvO6xlRDjs-5AixyD9vamWwTGlU&sensor=true&key=<mykey>
or this url:
https://maps.googleapis.com/maps/api/place/textsearch/json?pagetoken=ClRHAAAAqYa7IpwMQH3q1DyinfsMnkuOaZg8wQrp0pvzarv13pwqruqT2YfaEry6v_d-L4d_TC13G6iHuPz-rc1KbI6XRE01rB5CuXcHISu-CI_CaKESEMUxSjHhHDNee4xbr2tPEZcaFPvO6xlRDjs-5AixyD9vamWwTGlU&sensor=true&key=<mykey>
I get a INVALID_REQUEST.
This is the code I use to run and fetch the results:
#Override
protected ArrayList<String> doInBackground(String... params) {
// When more then one category is selected, this character needs to be after it.
final String DELIMITINGCHARACTER = "|";
// Add all the categories to a variable to put later on in the URL.
String myTypes = "";
for (String category : params){
// A category must be lowercase letters only.
category = category.toLowerCase();
// A category may not display a whitespace.
// The whitespace(s) must be replaced with a '_'.
category = category.replaceAll(" ", "_");
myTypes += category + DELIMITINGCHARACTER;
}
// Delete if the string ends with the delimitingcharachter the delimitingcharacter!
if (myTypes.endsWith("|")){
myTypes = myTypes.substring(0, myTypes.length() - 1);
}
ArrayList<String> myPointsOfInterest = new ArrayList<String>();
try{
String urlString;
String urlData;
//String urlApi = "&sensor=true&key=<myKey>"; // Key 1
String urlApi = "&sensor=true&key=<myKey>"; // Key 2
if (_txtFindLocation.getText().length() > 0){
urlString = "maps.googleapis.com/maps/api/place/textsearch/json?";
urlData = "query=" + URLEncoder.encode(myTypes, "UTF-8") + "+in+"
+ URLEncoder.encode(_txtFindLocation.getText().toString(), "UTF-8");
}
else{
urlString = "maps.googleapis.com/maps/api/place/search/json?";
urlData = "location=" + _myCurrentPosition.getLatitudeE6() / 1e6 + "," + _myCurrentPosition.getLongitudeE6() / 1e6
+ "&radius=5000&types=" + URLEncoder.encode(myTypes, "UTF-8");
}
ArrayList<String> myJsonString = new ArrayList<String>();
myJsonString.add(getDataOfUrl(urlString, urlData, urlApi, null));
for (String jsonString : myJsonString){
// Turn String into a JSON Object.
JSONObject jsonPredictionsObject = new JSONObject(jsonString);
String urlToken = jsonPredictionsObject.optString("next_page_token");
if (urlToken != ""){
myJsonString.add(getDataOfUrl(urlString, urlData, urlApi, "&pagetoken=" + urlToken));
}
}
Log.d("MainActivity", "size of myJsonString " + String.valueOf(myJsonString.size()));
for (String jsonString : myJsonString){
Log.d("MainActivity", jsonString);
// Turn String into a JSON Object.
JSONObject jsonPredictionsObject = new JSONObject(jsonString);
// Get a JSON Array that is inside the JSON Object.
JSONArray jsonPredictionsArray = jsonPredictionsObject.getJSONArray("results");
for (int i = 0; i < jsonPredictionsArray.length(); i++){
jsonPredictionsObject = (JSONObject) jsonPredictionsArray.get(i);
final String name = jsonPredictionsObject.getString("name");
final String vicinity = jsonPredictionsObject.optString("vicinity").compareTo("") != 0 ? jsonPredictionsObject.optString("vicinity") : jsonPredictionsObject.optString("formatted_address");
final JSONObject geometryObject = jsonPredictionsObject.getJSONObject("geometry");
final JSONObject locationObject = geometryObject.getJSONObject("location");
final JSONArray typesArray = jsonPredictionsObject.getJSONArray("types");
final double latitude = locationObject.getDouble("lat");
final double longitude = locationObject.getDouble("lng");
String types = "";
for (int t = 0; t < typesArray.length(); t++){
String type = typesArray.getString(t);
type = type.toLowerCase();
type = type.replaceAll("_", " ");
types += type + " - ";
}
types = types.substring(0, types.length() - 2);
myPointsOfInterest.add(String.valueOf(latitude) + DELIMITINGCHARACTER +
String.valueOf(longitude) + DELIMITINGCHARACTER + types +
DELIMITINGCHARACTER + name + DELIMITINGCHARACTER + vicinity);
}
}
}
catch (IOException e){
Log.e("Search points of interest", "GetPointsOfinterest: doInBackGround", e);
}
catch (JSONException e){
Log.e("Search points of interest", "GetPointsOfinterest: doInBackGround", e);
}
return myPointsOfInterest;
}
public String getDataOfUrl(String urlString, String urlData, String urlApi, String urlToken){
try{
URL myURL;
if (urlToken == null) {
myURL = new URL("https://" + urlString + urlData + urlApi);
}
else {
Log.d("URL INPUT", "https://" + urlString + urlData + urlToken + urlApi);
myURL = new URL("https://" + urlString + urlData + urlToken + urlApi);
}
URLConnection myURLConnection = myURL.openConnection();
BufferedReader myBufferReader = new BufferedReader(new InputStreamReader(myURLConnection.getInputStream()));
String strLine;
StringBuffer strBuffer = new StringBuffer();
// Take Google's legible JSON and turn it into on big String.
while((strLine = myBufferReader.readLine()) != null){
strBuffer.append(strLine);
}
Log.d("URL OUTPUT", strBuffer.toString());
return strBuffer.toString();
}
catch (IOException e){
Log.e("getDataOfUrl", "Error: ", e);
}
return null;
}
This is the output of logcat:
11-03 14:47:13.832: D/URL OUTPUT(19532): { "html_attributions" : [], "next_page_token" : "ClRHAAAAqYa7IpwMQH3q1DyinfsMnkuOaZg8wQrp0pvzarv13pwqruqT2YfaEry6v_d-L4d_TC13G6iHuPz-rc1KbI6XRE01rB5CuXcHISu-CI_CaKESEMUxSjHhHDNee4xbr2tPEZcaFPvO6xlRDjs-5AixyD9vamWwTGlU", "results" : [ { "formatted_address" : "Meldertstraat 42, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9311660, "lng" : 5.3423240 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", "id" : "e6ba73e5b439dddb83aaefc94c71954da0cb0268", "name" : "Café Café", "rating" : 4.40, "reference" : "CnRpAAAAdVZpUI4NKwsAiQTOjbYG9psNbU7awZkS6_8Ee4r3AvCKhpqWeiDqdof7zYmoUZWKj0A8rOwtncSa1YFVNNo6RxFmmHvuNdWCaucTqkuSSDw8E2o0pf5E6EiMj-7-Hd5xBzDtC0j9d5lLcVWW3AQy1xIQRwgfWwrZkyK65blCeGqhFhoUB9kTW5QVD9sNNuF75MvVewYTcxA", "types" : [ "cafe", "food", "establishment" ] }, { "formatted_address" : "Kempischesteenweg 27, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9350770, "lng" : 5.3397760 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", "id" : "dc66d311b3c4f5d1a87d5959dfdbc7616ad10b24", "name" : "Oberonn", "opening_hours" : { "open_now" : true }, "reference" : "CnRlAAAA5q-rz_aOTWsFGQIJz_6zyLbXIczXOTq4PVFxniOjxsCwnw7uIfY8tu7Jk-QbJ-arMWgdClnSpX28q2SqxD8021LGWcaf4Sgo9MaXWpoD6c4TSagyVO9_l_HUXgMoOFJzhHG_NH6z-t1DPxT1zD19PhIQ2gBP9cLazKeB96ZDTpFdsxoUVGB2Ddhrq6JUoTJgrHGL-SINOWk", "types" : [ "cafe", "food", "establishment" ] }, { "formatted_address" : "Willekensmolenstraat 41, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9316830, "lng" : 5.3470750 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", "id" : "04937541c2bf71ebec7ac13d506dbbd2727e1ce3", "name" : "Den Drossaerd", "reference" : "CnRqAAAA0cPmuMx0_J4x-o-yn0oT1D3kD-IHYAQPotAPPeDD3DWh2FXkD89kCsYoUGDLBlH2mKY6ju18JyCHvc4W_izLcd6TUOIoXrbUCyrtxOL4sTAFb41kH1aFT4dOBgvigYrGIcV8Qbzq-K4YGL3t7pnf1hIQKmUp-LLqtGHb4waYi2nq8hoU3VgwykpytoSUUPe2Ue1HmPrMRtE", "types" : [ "cafe", "food", "establishment" ] }, { "formatted_address" : "Leopoldplein 1, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9275810, "lng" : 5.3363830 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png", "id" : "cc30d6f4e6b0db1ed6dfd17bac118bbf78f194ae", "name" : "Century (Hotel)", "rating" : 3.80, "reference" : "CnRsAAAAfw4ucOBllDjMCtRU9epYQelpKHRx3u8JR8jr4I5jFzJsktNn3Un-3LjKKWtXCk3Unofi_6RhPFw9Tp8VU_Z7i-WOa00P-pirtCDjQPxg7sp470Mgh6_6PQspGG39H3k-VIMuUz9HWmoP3sPjump6SRIQTp1LZghfi-_HVaMfQArGPxoU-6ogK2IGMiueMEXP9mFiHlGJmo8", "types" : [ "lodging", "establishment" ] }, { "formatted_address" : "Maastrichterstraat 30, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9295410, "lng" : 5.3391230 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", "id" : "352f9da4642588aba419353487b210baeb30ddd3", "name" : "In De Kleine Hal", "reference" : "CnRuAAAAAlnMpdiL4Kluiw1T0-QgKWFv9wwWvrSY4w-B7SLI7gvpqT0FYaMTl6DhxncPLqRyxOTWxw3DP3r1XvNHDKXnAb3eRM-gZYwIqbvzVq62zEZgGw0usQgf48mAWOrDpegdNLnEFRYkIduRwlDMDyIOyBIQlDs9BozH4m_gE-dZKZf7yxoUqw0H_HT_IQnLaVm0YwG1QV7o3kg", "types" : [ "cafe", "food", "establishment" ] }, { "formatted_address" : "Fruitmarkt 32, Hasselt, België", "geometry" : { "location" : { "lat" : 50.9299760, "lng" : 5.3393550 } }, "icon" : "http://maps.gstatic.com/mapfiles
11-03 14:47:13.864: D/URL INPUT(19532): https://maps.googleapis.com/maps/api/place/textsearch/json?query=cafe+in+Elfde-Liniestraat%2C+Hasselt%2C+Belgium&pagetoken=ClRHAAAAqYa7IpwMQH3q1DyinfsMnkuOaZg8wQrp0pvzarv13pwqruqT2YfaEry6v_d-L4d_TC13G6iHuPz-rc1KbI6XRE01rB5CuXcHISu-CI_CaKESEMUxSjHhHDNee4xbr2tPEZcaFPvO6xlRDjs-5AixyD9vamWwTGlU&sensor=true&key=<myKey>
11-03 14:47:13.989: D/URL OUTPUT(19532): { "html_attributions" : [], "results" : [], "status" : "INVALID_REQUEST"}
PS: When I past the code in my browser (with next_page_token) both ways are correct, only I my Android app I get no valid data. AND yes I have a API Key, but I removed it here from both the code and my logcat output.
Anyone a idea what I'm doing wrong here?
EDIT
When I hardcode my url (with next-page-token) in Android, and afterwords let it run. I get the data that I expected, so no Invalid_Request is returned. The problems lays somewhere in building the url in Android, or the usage of the URL-class.

Found the answer on my own question: after a while, I just needed to check my output of logcat better.
The times of the request en times when the data was sent back from google.
output time of request 1: 14:47:13:832
input time of request 2: 14:47:13:864
output time of request 2: 14:47:13:989
These times are to close to each other, in my opinion Google thought I was a spammer/hacker or something and denied me access to the server on the second request.
The solution for me is wait 1 second if there is a next_page_token and then send the followup request.

Related

Android Studio - Parse from JSON ( Google Maps Api)

I need to extract the location type from where I am on the map for example from the following JSON :
(I deleted some of the irrelevant information in the fields)
{ "html_attributions" : [],
"results" : [
{ "business_status" : "OPERATIONAL", "geometry" :
{ "location" : { "lat" : 31.7895094,"lng" : 34.6444928},
"viewport" :
{"northeast" : {"lat" : 31.790,"lng" : 34.645}, "southwest" : {"lat" : 31.788,"lng" : 34.643} } },
"icon_mask_base_uri" : "",
"name" : "",
"opening_hours" : {"open_now" : true },
"photos" : [ { "height" : 709,
"html_attributions" : [],
"photo_reference" : "", "width" : 960 }],
"place_id" : "",
"plus_code" : {"compound_code" : "QJQV+RQ Ashdod, Israel",
"global_code" : "8G3PQJQV+RQ"},
"rating" : 3.9,
"reference" : "","scope" : "GOOGLE",
"types" : [ "electrician", "point_of_interest", "establishment" ],
"user_ratings_total" : 18,
"vicinity" : ""}],
"status" : "OK"}
I'm having trouble because the location type can be empty or can be a single location or can be several location types that come in an array.
The cases I need to handle:
If it's an array, I want only the first type (as in the attached example)
If it is a single location I want to extract it
If there is no location do not try to extract a location type at all
In the example above i need extract only "electrician" from types
This is how my code looks without extracting the types field:
public class FetchData extends AsyncTask<Object,String,String> {
String googleNearByPlacesData ;
GoogleMap googleMap;
String url;
String temp;
#Override
protected void onPostExecute(String s) {
//This is the exampale print
Log.d("json?" ,s);
try{
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("results");
for (int i= 0 ; i < jsonArray.length() ; i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject getLocation = jsonObject1.getJSONObject("geometry").
getJSONObject("location");
String lat = getLocation.getString("lat");
String lng = getLocation.getString("lng");
JSONObject getName = jsonArray.getJSONObject(i);
String name = getName.getString("name");
LatLng latLng = new LatLng(Double.parseDouble(lat),Double.parseDouble(lng));
MarkerOptions maekerOptions = new MarkerOptions();
maekerOptions.title(name);
maekerOptions.position(latLng);
googleMap.addMarker(maekerOptions);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,15));
}
} catch (JSONException e) {
e.printStackTrace();
}
}

How to draw route from A to B through multiple points on GoogleMaps?

Imagine I want to go from A to B through 3 waypoints. I have this code, which forms the Google Maps direction URL:
fun getMapsApiDirectionsUrl(): String {
val origin = "origin=" + currentLocation.latitude + "," + currentLocation.longitude;
val waypoints = "waypoints=optimize:true|" + loc1.latitude + "," + loc1.longitude + "|" + loc2.latitude + "," + loc2.longitude + "|" + loc3.latitude + "," + loc3.longitude
val destination = "destination=" + loc4.latitude + "," + loc4.longitude
val sensor = "sensor=false"
val key = "key="+API_KEY;
val params = "$origin&$waypoints&$destination&$sensor&$key"
val output = "json"
val url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + params
System.out.println("map url: "+url)
return url
}
Opening the URL on browser gave this:
{ "routes" : [], "status" : "ZERO_RESULTS" }
But if I only use 1 waypoint (instead of 3 like shown above), the direction will be displayed in 1 big JSON correctly, like this:
{ "geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"place_id" : "ChIJH87yjIXxaS4R5_ww8ZCufeo",
"types" : [ "clothing_store", "establishment", "point_of_interest", "store" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJ1wVXzIDxaS4RkyUYgf3ZV0c",
"types" : [ "street_address" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJrfOSGBXxaS4Ro595K_5ClCg",
"types" : [ "establishment", "hospital", "point_of_interest" ]
} ], "routes" : [
{
"bounds" : {
"northeast" : {
"lat" : -6.2399232,
"lng" : 106.8161445
},
"southwest" : {
"lat" : -6.2684858,
"lng" : 106.7929824
}
},
"copyrights" : "Map data ©2019 Google",
"legs" : [
{
"distance" : {
"text" : "1.2 km",
"value" : 1205
},
"duration" : {
"text" : "4 mins",
"value" : 254
},
"end_address" : "Jl. Kemang Raya No.54, RT.8/RW.2, Bangka, Kec. Mampang Prpt., Kota Jakarta Selatan, Daerah Khusus
Ibukota Jakarta 12730, Indonesia",
"end_location" : {
"lat" : -6.263443499999999,
"lng" : 106.8160131....
So does it mean I can only use 1 waypoint?
There is no way from origin to destination via waypoints set. The second URL:
https://maps.googleapis.com/maps/api/directions/json?origin=-6.2684059,106.8103103&waypoints=optimize:true%7C-6.263459,106.815903%7C-6.240607,106.792831%7C-6.240607,106.792831&destination=-6.235759,6.823277&sensor=false&key=<YOUR_KEY>
contains unreachable destination destination=-6.235759,6.823277 in Atlantic Ocean. Probably destination should be 106.823277 instead of 6.823277 : destination=-6.235759,106.823277 if all the positions should refer to valid locations in Jakarta. So, double check code, that compose URL for Directions API request.

Getting results of nearby places from User's Location using Google Maps API in Android

This is the first time using google map API and google places API. I am doing a demo application that displays the list hospitals (for example) nearest to the user's location with routes to each of the hospitals. I been able to get the user's location with the code below the:
public class MainActivity extends ActionBarActivity {
private GoogleMap map;
UiSettings mapSettings;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
if (map != null) {
// map.addMarker(new MarkerOptions().position(myLocation).title("Start"));
map.setMyLocationEnabled(true);
mapSettings = map.getUiSettings();
mapSettings.setScrollGesturesEnabled(true);
mapSettings.setZoomControlsEnabled(true);
}
}
}
The xml file:
<RelativeLayout 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">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</RelativeLayout>
My question how do I get the list of hospitals using google places API and display them. Any help,tips,walkthrough or tutorials will really be appericaited.Thanks in Advance.
For Android, I tried to use Place picker for Android. It can add the built-in place picker UI widget to your app, so users can choose from a set of nearby places displayed on a map. It easy to use, you just need to do is:
int PLACE_PICKER_REQUEST = 1;
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
startActivityForResult(builder.build(this), PLACE_PICKER_REQUEST);
It will show the UI below to pick a place for you, and you can get the place info by using below:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
Place place = PlacePicker.getPlace(data, this);
String toastMsg = String.format("Place: %s", place.getName());
Toast.makeText(this, toastMsg, Toast.LENGTH_LONG).show();
}
}
}
For more details, please refer to guide here and code here.
However, it cannot set the place type because it no feature for the Build in UI.. If you really need to set, you should use Google Places API Web Service API here, search the location yourself, parse the JSON data, and show on your own UI.
A Nearby Search lets you search for places within a specified area. You can refine your search request by supplying keywords or specifying the type of place you are searching for.
A Nearby Search request is an HTTP URL of the following form:
https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters
Note that in parameters you need to set types=hospital
EDIT
Example on how to pass the search request for specific locations in JSON using the google places API web API web service API.
Request
location: -33.8670,151.1957
radius: 500
types: food
name: cruise
key: API_KEY
Url for this:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670,151.1957&radius=500&types=food&name=cruise&key=API_KEY
and Response JSON like this:
{
"debug_log" : {
"line" : []
},
"html_attributions" : [],
"logging_info" : {
"experiment_id" : [],
"query_geographic_location" : "AU"
},
"results" : [
{
"geometry" : {
"location" : {
"lat" : -33.86879,
"lng" : 151.194217
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
"id" : "21a0b251c9b8392186142c798263e289fe45b4aa",
"name" : "Rhythmboat Cruises",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 426,
"html_attributions" : [
"\u003ca href=\"https://www.google.com/maps/views/profile/104066891898402903288\"\u003eRhythmboat Cruises\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAA-YL_I_Gk02blOX6S0nKHry8PFu9pDyp3Y9AnqISsa3Eq8mkbdD5mXuu1Fax60s0nSy3iiX-h5j-ztyLHcc1-782MsLQsgLLa4t3ZgDmCMll-a8ABapZGnZwDKByk67LFEhBgedv_u_eYFsEo9ay8jxJjGhTUHKPJ4G82vBJqSNliuv7UlAtclw",
"width" : 640
}
],
"place_id" : "ChIJyWEHuEmuEmsRm9hTkapTCrk",
"reference" : "CnRmAAAAvQlMKw-XtxEY4vWFCvudF7CEMQGI5ycNbfVgGl9rAF75fdiPOiLJw1k9NL2v8ZIJsOJuRS3Lm9Dw1vga4ajycAs7PlxN1MVnnYT9la0pBvEvSQNlyvszKANS1R4P7Mvk_jhqswMggqCUtwJ13LN2hRIQOiAkLTWUi3DOjVVOw7J5IRoUb_cJyJaJNqKdmkDM2f0OjQjh9F0",
"scope" : "GOOGLE",
"types" : [ "restaurant", "food", "point_of_interest", "establishment" ],
"vicinity" : "Pyrmont Bay Wharf (Near Australia Maritime Museum), Pyrmont, NSW 2009"
},
{
"geometry" : {
"location" : {
"lat" : -33.867591,
"lng" : 151.201196
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
"id" : "a97f9fb468bcd26b68a23072a55af82d4b325e0d",
"name" : "Australian Cruise Group",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 1331,
"html_attributions" : [
"\u003ca href=\"https://www.google.com/maps/views/profile/110751364053842618118\"\u003eAustralian Cruise Group\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAtEoj29FJcNBccrsu6bHt0xgwVGhYlciCY1fe6gTr_d5_KkeP3LITnOwnpNRJWnX39B04-aIBOKXKJH6ltx948T5vWIYBoah1yZDXsWngWZ5kMsK7xyCB5P_q_xBIBxxUEhAYWeB4PiOm_Jy093fB-j0iGhSYmIs9xB2aa6u-RH8V8lZEk-Q5ig",
"width" : 2000
}
],
"place_id" : "ChIJrTLr-GyuEmsRBfy61i59si0",
"reference" : "CnRqAAAAFbukrZvRNsc05TreHUCrPEya5NcN9v0fFLLaK-D1fSyxFTuQlUDhDstU3qwXKw_fADX4W6guUkexax1nufgiYIuGCKoZPEnup1r-LhGGNz9dn1uf9Of5iOtZ1XgCeDjJaYvGbSB3C0pAXL8r9kOsmhIQbx2Sia2DAWTjtSZwuh5aehoUhM6upqBCDLhGruZAGGsCOwAiIq8",
"scope" : "GOOGLE",
"types" : [
"restaurant",
"travel_agency",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "32 The Promenade, King Street Wharf 5, Sydney"
},
{
"geometry" : {
"location" : {
"lat" : -33.870943,
"lng" : 151.190311
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/bar-71.png",
"id" : "e644f7f34cf875b9919c6548f1b721947362850a",
"name" : "Lunch Cruise with Jazz on Sydney Harbour",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 292,
"html_attributions" : [
"\u003ca href=\"https://www.google.com/maps/views/profile/105423912060796272053\"\u003eFrom a Google User\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAR4bqFTKYWdBwZwdBdON_JRD7V_joTwwIPwRUpZIZWkSSd8GQ3P2O-_aQbUJdL2RhoAyzCUIF0f--DI4oXFneTpj5zZfFq-iFiT7i_x0tjnDveIY8tJv-6o0uWSSjYqabEhCKqQWZqrKAoddjDcc64N48GhQZ2T1_ntPzNKCooHpZzlYQ7AxFOA",
"width" : 438
}
],
"place_id" : "ChIJLfySpTOuEmsRPCRKrzl8ZEY",
"reference" : "CoQBewAAAFd2fO_YWGTiT4RzXWb5tsOuOt7YyV_ScQOwm0tqJSrAyACCczeOzV-P_mgZLro1oKP_34Nt0nVC_1OEKAQUcd7cUm7xmAMSX-EkbSWiD0kOWGgGgKuDRtb0t_8qsxBGU_izugWCyK7SRWezTxELYNdkS0OEiSWPnvhxvXuQktBBEhAAtEe7fagW2kUR14T1QpVsGhQBO7YpIyYSPvo4zUJuL_bX30nJZw",
"scope" : "GOOGLE",
"types" : [ "bar", "restaurant", "food", "point_of_interest", "establishment" ],
"vicinity" : "37 Bank St, Pyrmont"
}
],
"status" : "OK"
}
The below example returns a list of hospitals near London, England.
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=51.503186,-0.126446&radius=5000&types=hospital&key=API_KEY
For more details please refer here.
Follow this link, it has all explained out,
in the String type='grocery_or_supermarket' replace it to be 'hospital' and you'll be good to go:
http://androidmastermind.blogspot.co.ke/2016/06/android-google-maps-with-nearyby-places.html
private void loadNearByPlaces(double latitude, double longitude)
//YOU Can change this type at your own will, e.g hospital, cafe, restaurant.... and see how it all works
{
mMap.clear();
Intent i = getIntent();
String type = hospital;
StringBuilder googlePlacesUrl =
new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
googlePlacesUrl.append("location=").append(latitude).append(",").append(longitude);
googlePlacesUrl.append("&radius=").append(PROXIMITY_RADIUS);
googlePlacesUrl.append("&types=").append(type);
googlePlacesUrl.append("&sensor=true");
googlePlacesUrl.append("&key=" + GOOGLE_BROWSER_API_KEY);
JsonObjectRequest request = new JsonObjectRequest(googlePlacesUrl.toString(),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject result) {
Log.i(TAG, "onResponse: Result= " + result.toString());
parseLocationResult(result);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "onErrorResponse: Error= " + error);
Log.e(TAG, "onErrorResponse: Error= " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(request);
}
This will load the near by hospital according to your location.
Follow below code:
private static final String TAG_RESULT = "predictions";
JSONObject json;
ArrayList<String> names;
ArrayAdapter<String> adapter;
String browserKey = "Google API key";
//------------------------AutoComplete code--------------
public void updateList(String place) {
String input = "";
try {
input = "input=" + URLEncoder.encode(place, "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String output = "json";
String parameter = input + "&types=geocode&sensor=true&key=" + browserKey;
url = "https://maps.googleapis.com/maps/api/place/autocomplete/" + output + "?" + parameter;
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url,
null, new Response.Listener<JSONObject>() {
#Override public void onResponse(JSONObject response) {
System.out.println("response"+response);
try {
JSONArray ja = response.getJSONArray(TAG_RESULT);
for (int i = 0; i < ja.length(); i++) {
JSONObject c = ja.getJSONObject(i);
String description = c.getString("description");
System.out.println("description"+description);
names.add(description);
}
adapter = new ArrayAdapter<String>(
getApplicationContext(),
android.R.layout.simple_list_item_1, names) {
#Override public View getView(int position,
View convertView, ViewGroup parent) {
View view = super.getView(position,
convertView, parent);
TextView text = (TextView) view
.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
return view;
}
};
edittext_signup_city.setAdapter(adapter);
adapter.notifyDataSetChanged();
} catch (Exception e) {
}
}
}, new Response.ErrorListener() {
#Override public void onErrorResponse(VolleyError error) {
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq, "jreq");
}

JsonArray, finding index? or multiple items in an array

in this example, i like to know which city is closer to Vancouver. Victoria , Washington or Texas? one I find shortest distance how can I see which destination_address this value belong to?
{
"destination_addresses" : [
"Victoria, BC, Canada",
"Texas, États-Unis",
"Washington, District de Columbia, États-Unis"
],
"origin_addresses" : [ "Vancouver, BC, Canada" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "135 km",
"value" : 134638
},
"duration" : {
"text" : "6 heures 37 minutes",
"value" : 23815
},
"status" : "OK"
},
{
"distance" : {
"text" : "3 457 km",
"value" : 3456694
},
"duration" : {
"text" : "7 jours 15 heures",
"value" : 658855
},
"status" : "OK"
},
{
"distance" : {
"text" : "5 000 km",
"value" : 4999636
},
"duration" : {
"text" : "11 jours 2 heures",
"value" : 956487
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
I'm trying to find closest city to Vancouver by parsing the distance & find min distance. by finding that we see shortest distance belongs to Victoria. How canI say this min distance belongs to Victoria.
this is my code for finding closest city ( shortest distance)
public class MainActivity extends Activity {
HttpClient client;
double minDistance=0;
String destination_addresses;
JSONArray rows;
JSONArray elements;
final static String URL= "http://maps.googleapis.com/maps/api/distancematrix/json?origins=Vancouver+BC&destinations=San+Francisco|Victoria+BC&mode=bicycling&language=fr-FR&sensor=false";
protected void OnCreate (Bundle savedInstanceState ){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
client = new DefaultHttpClient();
}
public JSONObject ClosestObject (String Origin) throws ClientProtocolException, IOException , JSONException {
StringBuilder url= new StringBuilder (URL);
HttpGet get = new HttpGet(url.toString());
HttpResponse r = client.execute(get);
int status = r.getStatusLine().getStatusCode();
if (status == 200){
HttpEntity e = r.getEntity();
String data = EntityUtils.toString(e);
JSONArray locations = new JSONArray(data);
for (int i=0; i< locations.length(); i++){
rows= (JSONArray) locations.getJSONObject(2).get("rows");
elements= (JSONArray) locations.getJSONObject(0).get("elements");
String Value= elements.getJSONObject(i).toString();
double distanceValue = Double.parseDouble(Value);
if ( distanceValue< minDistance){
minDistance= distanceValue;
}
}
}
By the code you have given you are getting the JSON from Google url so you should read the documentation of the API, you will definitely get your answer there.
EDIT: and if you want to traverse the JSON array you can use yourjsonarray.getJSONObject(index).getString("Distance").
Try it :)
JSONObject bigData = new JSONObject(data);
rows = bigData.getJSONArray("rows");
elements = rows.getJSONObject(0).getJSONArray("elements");
JSONObject ob = elements.getJSONObject(0);
String value = ob.getJSONObject("duration").getString("value");//or "distance"
minDistance = Double.parseDouble(value);
int index = 0;
for (int i = 1; i < elements.length(); i++) {
ob = elements.getJSONObject(i);
value = ob.getJSONObject("duration").getString("value");//or "distance"
double distanceValue = Double.parseDouble(value);
if (distanceValue < minDistance) {
minDistance = distanceValue;
index = i;
}
}
JSONArray closers = bigData.getJSONArray("destination_addresses");
String closer = closers.getString(index);
Log.d("closer", closer);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

Google Places JSON Throws a Parsing Error in Android

I'm writing an android app that takes your current location and returns a list of the stores near you using the Google Places web service. I'm able to get back (what I think is) valid JSON, but when I go to parse the JSON using the Android JSONObject library, I get a parsing error.
Here is my class:
public class StoresNearMe {
private String result = "";
private String googleAPIKey = "Omitted for this example";
private String searchRadius = "50";
private Location myLocation;
final String TAG = getClass().getSimpleName();
public StoresNearMe(Location location){
myLocation = location;
}//StoresNearMe
public String getStoresNearMe(){
String result = "Nothing";
result = callGoogleWebService(buildURLForGooglePlaces(myLocation));
convertJSONtoArray(result);
return result;
}//getStoresNearMe
private String callGoogleWebService(String url){
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
//request.addHeader("deviceId", deviceId);
ResponseHandler<String> handler = new BasicResponseHandler();
try {
result = httpclient.execute(request, handler);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
httpclient.getConnectionManager().shutdown();
return result;
}//callWebService
private String buildURLForGooglePlaces(Location location){
String baseUrl = "https://maps.googleapis.com/maps/api/place/search/json?";
String lat = String.valueOf(location.getLatitude());
String lon = String.valueOf(location.getLongitude());
String url = baseUrl + "location=" + lat + "," + lon + "&" +
"radius=" + searchRadius + "&" + "sensor=false" +
"&" + "key=" + googleAPIKey;
Log.d(TAG,url);
return url;
}//buildURLForGooglePlaces
private void convertJSONtoArray(String rawJSON){
try {
JSONObject completeJSONObj = new JSONObject(rawJSON);
String json = completeJSONObj.toString();
Log.d(TAG,json);
JSONObject results = completeJSONObj.getJSONObject("results");
} catch (JSONException e) {
Log.d(TAG,"JSON parsing error - fix it:" + e.getMessage());
}
}//convertJSONtoArray
}//StoresNearMe
Here is the JSON returned by my call:
{
"html_attributions" : [
"Listings by \u003ca href=\"http://www.yellowpages.com.au/\"\u003eYellow Pages\u003c/a\u003e"
],
"results" : [
{
"geometry" : {
"location" : {
"lat" : -33.86694910,
"lng" : 151.19549870
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"id" : "96760d4544ecdaaf2e87565915638238ca960f20",
"name" : "Pirrama Rd",
"reference" : "CnRqAAAAL0xKaK8vGlVlD-E5j-88K9YTuCKlOFfoBxhBUwMIBGxNQDC8UdkULJiiC0ICBRxpddCV09wyc-HtShEpquP-drX4sj4tI_tbfveDIbzfSAUaNQjYhhfjQ-eVi0VeWBXdXH0A8Z_-nKXKMo1fvCHtBhIQlAeLnFtotWnYonMUpU1DqxoUcI1weYioNnJPtnhXCThmx0W0ubU",
"types" : [ "route" ],
"vicinity" : "Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8669710,
"lng" : 151.1958750
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"name" : "Google Sydney",
"reference" : "CnRkAAAAqvesgoigCyiZfDUwqjbravZHH5zsXrmskbQVhkFk1JMnnrnKNGQyoHBBYofTML_zZqaAUAKJeJCvReUn62oGzSgPgNSjWaXUVorKGDXAAjhGyeh2pRrJFwuC5qsgBYdyN4kY8kspJGu_bMo3xrranxIQ-mFIK_28TAqiagOAzY7RiBoUrZTvFJYSn0OXimLRRb_SQ3OKW44",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Road, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8670840,
"lng" : 151.195950
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "27e84d1acda19c14b9c7f5271242796891bc9c9e",
"name" : "Accenture",
"reference" : "CoQBfQAAAOpBriMi1e4itUquHQnv_jQyEOibrEnbWfAuJBJqBUzcTqNvY6luCcgiqHr3ensEO81bcTkt4fXGHFLxM7pERmxVvFnRnLsLy5xyQtVxIp8eQnYP6AZxLZyxbfGceG87r6A1lHCOQTFxK85HVFq7pYik9ud_ExxEtwHT3gO54pihEhDYEZ59AYpLMDmlRHk5__q_GhQdTS2wSOU2sAxy0j4J7EYwCuq6Iw",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Road, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8670520,
"lng" : 151.1957360
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "3ef986cd56bb3408bc1cf394f3dad9657c1d30f6",
"name" : "Doltone House - Darling Island Wharf",
"reference" : "CoQBewAAAExUq-YlS-bahqAJeJbfyGfkUrqyuKjZgCPxHznMZsHg1aHLWoFk8s_04DxDtEFAlSyRP-ZHNsceha6MB8JD7zFMjbYOKNJLSm9OcgFUOFB-4SZP3ZeRyYzna2032gayzUU1_8N-qtb_r2kfllGYAmgnaU7h6RC8haaf-dFfvdiiEhBUdWHpEeL7qwtB91BgNYdPGhTAjf0Xa7-MKHJRRCQu_g7XL80dzQ",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Road, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8671110,
"lng" : 151.1958750
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "258f23471a33cfa2828170660d94cd5797edb18c",
"name" : "Workplace6",
"reference" : "CnRhAAAAi_hm5c3gpntkNvC7NbQtIe5tcmosCIHHbzqhLURaH7mQ6inEOqg47_cltBrtFBEPSIqCuPQDC3UA-suLBfRslIwUNytKjC87Lt1ZrGXF6ZmnOR2rVcdCGdoWrdi977RHruBO21zbjzVWE-A3ZDn2NBIQ1Vu2-nr3E02DuJAtXL8x4BoUEBRWEHReK2LO3IoldvyyvSKb0Qs",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Rd, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8670520,
"lng" : 151.1957360
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "fe9136d6406ed2d35660dea37a0be34043c1a4f2",
"name" : "Doltone House",
"reference" : "CnRjAAAAo4zx1lM-veFEPBBeIRFETZoH8QRMmpHIBVtnmfOZ-Sh1-8p4vxKj-146pHGW6wPCZxIV0iIuAGow9OSsHubvY_kSnlBe5OB99ZSxHQsm0LrLh45c05Gf7C8jwp_9D7keDVDAC47MN65niSZW71fOrRIQxODppLktQZFWbf-V1N4gHxoUPetbj0zbU1kQj96YrRLzLKrbMoE",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Road, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.8666470,
"lng" : 151.195650
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "2722b46120160ec0a322e0a13cb0717ed41a696b",
"name" : "Biaggio",
"reference" : "CmRdAAAAp7wiB1b9cK-26FjhO2DVAGA-5uzuZxppHqCkR75dQxoMJiLD5G7H90_dKtNVDlRAdKSOx7hWlUoHGuwkbBA4ZhNIDrPdLWQ1a41sEN9gZJvU-t7uxoRzziZpTVSCU-AXEhDoQ36icc3OBaMH1xxnPgsEGhTB08nD6Q67ojrGYMJWrd4PojJKsw",
"types" : [ "establishment" ],
"vicinity" : "Pirrama Rd, Pyrmont"
},
{
"geometry" : {
"location" : {
"lat" : -33.86954560,
"lng" : 151.19454040
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"id" : "40840d476baa531e0227a353b1bef70262f66e7e",
"name" : "Pyrmont",
"reference" : "CnRnAAAA7aHZwg2JyjTI-xotS1q4XKgbg3eCUwOZm3Nz55Xf5Q2w-nZpBrrd2VAEl60On0puVl8bX7UaJTIECELr3KY2mL4s7zsIznItOiJEG-9QMlnreRSmxSBSUAkPghKWoq4OFbCr0dwNtZSKJFazcbCc1BIQSz5BZfCm-iyMZ8YOgvc4tBoU1CdnwsHS5PhB69jpYHsOvfWXEgo",
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}
Any help is appreciated - I'm not sure what is going wrong.
Thanks!
The problem is that you're trying to read an array in as an object.
Change
JSONObject results = completeJSONObj.getJSONObject("results");
to
JSONArray results = completeJSONObj.getJSONArray("results");
and the parse exception goes away.
your JSON should be Valid : example :
{\"key\":\"value\" }

Categories

Resources