• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Android Store and call next_page_token

Ad621

Newbie
Apr 7, 2016
14
0
Hi Guys! new here and im kinda stuck on a small issue. im working with google places on a small application m making and i'm currently able to show 20 markers on the map. I have a floating action button on my map screen and I was just wondering if theres a way to store and call the next_page_token so that when the user clicks on the floating button then it would display the 20 markers from the next page. I have the following code: (Lines 40 to 74)

Code:
 public class MapsActivity extends FragmentActivity implements LocationListener {

    GoogleMap mMap;
    double mLatitude = 0;
    double mLongitude = 0;
    HashMap<String, String> mMarkerPlaceLink = new HashMap<String, String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mMap = mapFragment.getMap();
        // Enabling MyLocation in Google Map
        mMap.setMyLocationEnabled(true);
        mMap.getUiSettings().setCompassEnabled(true);
        mMap.getUiSettings().setZoomControlsEnabled(true);

        // Getting LocationManager object from System Service
        // LOCATION_SERVICE
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // Creating a criteria object to retrieve provider
        Criteria criteria = new Criteria();

        // Getting the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);

        // Getting Current Location From GPS
        Location location = locationManager.getLastKnownLocation(provider);

        // onLocationChanged(location);
        if (location != null) {
            onLocationChanged(location);
        }



        StringBuilder sb = new StringBuilder(
                "https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
        sb.append("location=" + mLatitude + "," + mLongitude);
        sb.append("&radius=1000");
        sb.append("&key=PLACES_KEY");
        // Creating a new non-ui thread task to download Google place json
        // data
        PlacesTask placesTask = new PlacesTask();

        // Invokes the "doInBackground()" method of the class PlaceTask
        placesTask.execute(sb.toString());

        // Will display 20 more places returned form the next_page_token
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_more);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Finding you some more places!", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();

                StringBuilder sb = new StringBuilder(
                        "https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
                sb.append("pagetoken=" );
                sb.append("&key=PLACES_KEY");
                // Creating a new non-ui thread task to download Google place json
                // data
                PlacesTask placesTask = new PlacesTask();

                // Invokes the "doInBackground()" method of the class PlaceTask
                placesTask.execute(sb.toString());

            }
        });

    }


    /**
     * A method to download json data from url
     */
    private String downloadUrl(String strUrl) throws IOException {
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(strUrl);

            // Creating an http connection to communicate with url
            urlConnection = (HttpURLConnection) url.openConnection();

            // Connecting to url
            urlConnection.connect();

            // Reading data from url
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(
                    iStream));

            StringBuffer sb = new StringBuffer();

            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            data = sb.toString();
            Log.d("data", "json response: " + data);
            br.close();

        } catch (Exception e) {
            Log.d("Exception while downloading url", e.toString());
        } finally {
            iStream.close();
            urlConnection.disconnect();
        }

        return data;
    }


    /**
     * A class, to download Google Places
     */
    private class PlacesTask extends AsyncTask<String, Integer, String> {

        String data = null;

        // Invoked by execute() method of this object
        @Override
        protected String doInBackground(String... url) {
            try {
                data = downloadUrl(url[0]);
            } catch (Exception e) {
                Log.d("Background Task", e.toString());
            }
            return data;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(String result) {
            ParserTask parserTask = new ParserTask();

            // Start parsing the Google places in JSON format
            // Invokes the "doInBackground()" method of the class ParseTask
            parserTask.execute(result);
        }

    }

    /**
     * A class to parse the Google Places in JSON format
     */
    private class ParserTask extends
            AsyncTask<String, Integer, List<HashMap<String, String>>> {

        JSONObject jObject;

        // Invoked by execute() method of this object
        @Override
        protected List<HashMap<String, String>> doInBackground(
                String... jsonData) {

            List<HashMap<String, String>> places = null;
            PlaceJSONParser placeJsonParser = new PlaceJSONParser();

            try {
                jObject = new JSONObject(jsonData[0]);

                /** Getting the parsed data as a List construct */
                places = placeJsonParser.parse(jObject);

            } catch (Exception e) {
                Log.d("Exception", e.toString());
            }
            return places;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(List<HashMap<String, String>> list) {

            // Clears all the existing markers
            mMap.clear();
            for (int i = 0; i < list.size(); i++) {

                // Creating a marker
                MarkerOptions markerOptions = new MarkerOptions();

                // Getting a place from the places list
                HashMap<String, String> hmPlace = list.get(i);

                // Getting latitude of the place
                double lat = Double.parseDouble(hmPlace.get("lat"));

                // Getting longitude of the place
                double lng = Double.parseDouble(hmPlace.get("lng"));

                // Getting name
                String name = hmPlace.get("place_name");

                String vicinity = hmPlace.get("vicinity");

                LatLng latLng = new LatLng(lat, lng);

                // Setting the position for the marker
                markerOptions.position(latLng);

                markerOptions.title(name);

                markerOptions.snippet(vicinity);

                // Placing a marker on the touched position
                Marker m = mMap.addMarker(markerOptions);

                // Linking Marker id and place reference

                mMarkerPlaceLink.put(m.getId(), hmPlace.get("reference"));

            }

        }
    }

    @Override
    public void onLocationChanged(Location location) {
        mLatitude = location.getLatitude();
        mLongitude = location.getLongitude();
        LatLng latLng = new LatLng(mLatitude, mLongitude);
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.animateCamera(CameraUpdateFactory.zoomTo(15));

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }
}

My JSONParser class:

Code:
public class PlaceJSONParser {



    /** Receives a JSONObject and returns a list */
    public List<HashMap<String,String>> parse(JSONObject jObject){

        JSONArray jPlaces = null;
        try {
            /** Retrieves all the elements in the 'places' array */
            jPlaces = jObject.getJSONArray("results");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        /** Invoking getPlaces with the array of json object
         * where each json object represent a place
         */
        return getPlaces(jPlaces);
    }


    private List<HashMap<String, String>> getPlaces(JSONArray jPlaces){
        int placesCount = jPlaces.length();
        List<HashMap<String, String>> placesList = new ArrayList<HashMap<String,String>>();
        HashMap<String, String> place = null;

        /** Taking each place, parses and adds to list object */
        for(int i=0; i<placesCount;i++){
            try {
                /** Call getPlace with place JSON object to parse the place */
                place = getPlace((JSONObject)jPlaces.get(i));
                placesList.add(place);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return placesList;
    }

    /** Parsing the Place JSON object */
    private HashMap<String, String> getPlace(JSONObject jPlace){

        HashMap<String, String> place = new HashMap<String, String>();
        String placeName = "-NA-";
        String vicinity = "-NA-";
        String latitude="";
        String longitude="";
        String reference="";


        try {
            // Extracting Place name, if available
            if(!jPlace.isNull("name")){
                placeName = jPlace.getString("name");
            }

            // Extracting Place Vicinity, if available
            if(!jPlace.isNull("vicinity")){
                vicinity = jPlace.getString("vicinity");
            }

            latitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
            longitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");
            reference = jPlace.getString("reference");


            place.put("place_name", placeName);
            place.put("vicinity", vicinity);
            place.put("lat", latitude);
            place.put("lng", longitude);
            place.put("reference", reference);


        } catch (JSONException e) {
            e.printStackTrace();
        }
        return place;
    }
}

Currently ive hardcoded the next_page_token into my code and it seems to work, but it only works once, any ideas on how i could call and retrieve it automatically using a variable?

Any info will be appreciated!
Thanks!
 
Last edited:
What's the "next_page_token"? Is it something returned by the google maps web service?
Yeh, when you run google maps/places in Android Studio, my terminal prints out 20 places that are close to me. These 20 places are on "one page" the next_page_token holds the other 20 places along with all their information such as location, name, address etc etc.
 
Upvote 0
Well it depends on the structure of your Json data, which isn't shown. It would be something similar to what PlaceJSONParser.parse() is doing, although that code is not shown either.

Once you have extracted the next page token from the returned data, assign it to a class variable, and use it in place of the constant value PLACES_KEY
 
Upvote 0
Well it depends on the structure of your Json data, which isn't shown. It would be something similar to what PlaceJSONParser.parse() is doing, although that code is not shown either.

Once you have extracted the next page token from the returned data, assign it to a class variable, and use it in place of the constant value PLACES_KEY

Ive edited my original post to include the JSONparser class.
So in my JSONParser class would i basically assign the next_page_token to a variable similar to how ive done with the Name and Vicinity?
 
Upvote 0
Well I'd create a new method on the JSONParser class to do it. You can create a class variable in JSONParser class called nextPageToken. Then define a method called getNextPageToken() which will extract the token from the Json.
Of course you need to know what the next page token element is called within the Json data structure. Do you know that? If not then you will need to examine jObject to see what it looks like.
 
Upvote 0
Well I'd create a new method on the JSONParser class to do it. You can create a class variable in JSONParser class called nextPageToken. Then define a method called getNextPageToken() which will extract the token from the Json.
Of course you need to know what the next page token element is called within the Json data structure. Do you know that? If not then you will need to examine jObject to see what it looks like.

Not really sure how to do that :/
Yes im able to see the next_page_token in my terminal although i believe its different for each page..
 
Upvote 0
Ok this would be an ideal point to learn how to set breakpoints in your code, and run your app in debug mode. If you set a breakpoint at the start of your parse() method, you can look at the jObject parameter and see what's in it.

But doesn't the google maps API documentation tell you what data is returned?
 
Upvote 0
Ok this would be an ideal point to learn how to set breakpoints in your code, and run your app in debug mode. If you set a breakpoint at the start of your parse() method, you can look at the jObject parameter and see what's in it.

But doesn't the google maps API documentation tell you what data is returned?

My terminal prints out the JSON data which is exactly the same as whats displayed on the google api website, similar to whats shown here: https://developers.google.com/places/web-service/search#PlaceSearchResponses
 
Upvote 0
there's only one way to find out.. :)

Does this look correct? i dont have any errors

Code:
    String next_page_token;

/** Receives a JSONObject and returns a list */
public List<HashMap<String,String>> parse(JSONObject jObject){

    JSONArray jPlaces = null;
    try {

        jPlaces = jObject.getJSONArray("results");
        next_page_token = jObject.getString("next_page_token");

    } catch (JSONException e) {
        e.printStackTrace();
    }

    return getPlaces(jPlaces);
}

public String getNext_Page_token(){
    return next_page_token;
}
 
Upvote 0
Okay so i created an object
Code:
private PlaceJSONParser getToken;

i then did

Code:
sb.append("pagetoken=" + getToken.getNext_Page_token());

and i keep getting an error
Code:
 Attempt to invoke virtual method 'java.lang.String com.example.test.outandabout.PlaceJSONParser.getNext_Page_token()' on a null object reference
 
Upvote 0
One other thing to be aware of is that the next_page_token is not always present in the returned data. It could be null, so you should put some defensive null-checking code in there, just to be on the safe side.

Yeah i just realised that it refreshes the map twice but then it says that there is no "next_page_token" soo would a simple if statement be enough to check if nextpagetoken is null and if so then to tell the user that theyve reached the end of the list?
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones