logo logo

How to Use Foursquare API on Android Application

Home » Information Technology » Programming » Android » How to Use Foursquare API on Android Application

This is my second post about using Oauth enabled API on Android. This time i’ll try to explain how to use Foursquare API V2 within Android application. I built my own Android implementation for Foursquare API based on my previous  implementation for Twitter API that can be used to post Twitter status from Android. To use Foursquare API within an Android application, first you have to register your application on Foursquare to get the client id and client secret key.

I. Register application

To register your application:

  • Go to Foursquare Oauth page and login with your username and password
  • After logged in, click the ‘REGISTER A NEW CONSUMER’ button
  • Fill the registration form with your application name, application website url and the callback url. For callback url, you can use any url or string if your app is for mobile application only, for example myapp://connect
  • <

  • After finishing the registration , you’ll get client id and client secret key that will be used later to connect to Foursquare from Android app.
II. Android Client Code

I’ve created my own implementation to handle oauth authentification with Foursquare. It is based on my previous Twitter implementation, but with slightly modification which more simple and uses no external libraries. To access all Foursquare API endpoints, first we have to get the access token. Here is my implementation flow:
  1. Get access token by letting user grant access to the app using a webview based authentication dialog
  2. Save access token on shared preferences
  3. Use the access token to access Foursquare API endpoints

I’ve included a sample project in this tutorial that can be downloaded on my github repo here. I’ll explain how to use my implementation based on the sample project. In my sample project, i create three classes used to handle authentication and connection to Foursquare: FoursquareApp.java (handle oauth authentification), FoursquareSession.java (save access token on shared preferences) and FoursquareDialog.java (webview authentication dialog).

Main.java

public class Main extends Activity {
	private FoursquareApp mFsqApp;
	private ListView mListView;
	private NearbyAdapter mAdapter;
	private ArrayList<FsqVenue> mNearbyList;
	private ProgressDialog mProgress;

	public static final String CLIENT_ID = "your client id";
	public static final String CLIENT_SECRET = "your client secret";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        final TextView nameTv 		= (TextView) findViewById(R.id.tv_name);
        Button connectBtn 			= (Button) findViewById(R.id.b_connect);
        final EditText latitudeEt	= (EditText) findViewById(R.id.et_latitude);
        final EditText longitudeEt	= (EditText) findViewById(R.id.et_longitude);
        Button goBtn				= (Button) findViewById(R.id.b_go);
        mListView					= (ListView) findViewById(R.id.lv_places);

        mFsqApp 		= new FoursquareApp(this, CLIENT_ID, CLIENT_SECRET);

        mAdapter 		= new NearbyAdapter(this);
        mNearbyList		= new ArrayList<FsqVenue>();
        mProgress		= new ProgressDialog(this);

        mProgress.setMessage("Loading data ...");

        if (mFsqApp.hasAccessToken()) nameTv.setText("Connected as " + mFsqApp.getUserName());

        FsqAuthListener listener = new FsqAuthListener() {
        	@Override
        	public void onSuccess() {
        		Toast.makeText(Main.this, "Connected as " + mFsqApp.getUserName(), Toast.LENGTH_SHORT).show();
        		nameTv.setText("Connected as " + mFsqApp.getUserName());
        	}

        	@Override
        	public void onFail(String error) {
        		Toast.makeText(Main.this, error, Toast.LENGTH_SHORT).show();
        	}
        };

        mFsqApp.setListener(listener);

        //get access token and user name from foursquare
        connectBtn.setOnClickListener(new OnClickListener() {
        	@Override
        	public void onClick(View v) {
        		mFsqApp.authorize();
        	}
        });

        //use access token to get nearby places
        goBtn.setOnClickListener(new OnClickListener() {
        	@Override
        	public void onClick(View v) {
        		String latitude  = latitudeEt.getText().toString();
        		String longitude = longitudeEt.getText().toString();

        		if (latitude.equals("") || longitude.equals("")) {
        			Toast.makeText(Main.this, "Latitude or longitude is empty", Toast.LENGTH_SHORT).show();
        			return;
        		}

    			double lat	= Double.valueOf(latitude);
    			double lon	= Double.valueOf(longitude);

        		loadNearbyPlaces(lat, lon);
        	}
        });
    }

    private void loadNearbyPlaces(final double latitude, final double longitude) {
    	mProgress.show();

    	new Thread() {
    		@Override
    		public void run() {
    			int what = 0;

    			try {

    				mNearbyList = mFsqApp.getNearby(latitude, longitude);
    			} catch (Exception e) {
    				what = 1;
    				e.printStackTrace();
    			}

    			mHandler.sendMessage(mHandler.obtainMessage(what));
    		}
    	}.start();
    }

    private Handler mHandler = new Handler() {
    	@Override
    	public void handleMessage(Message msg) {
    		mProgress.dismiss();

    		if (msg.what == 0) {
    			if (mNearbyList.size() == 0) {
    				Toast.makeText(Main.this, "No nearby places available", Toast.LENGTH_SHORT).show();
    				return;
    			}

    			mAdapter.setData(mNearbyList);
    			mListView.setAdapter(mAdapter);
    		} else {
    			Toast.makeText(Main.this, "Failed to load nearby places", Toast.LENGTH_SHORT).show();
    		}
    	}
    };
}

The example above shows how to authenticate user to get access token, display the webview authentication dialog then use the access token to access Foursquare API endpoint which in this example is to get the nearby venues.

Line 8-9: First, replace the CLIENT_ID and CLIENT_SECREET with your app client id and client secret
Line 24: Create an instance of FoursquareApp class and pass the CLIENT_ID and CLIENT_SECRET as parameters
Line 32: Check if user has access token (already authorized the app before) using hasAccessToken
method.
Line 34: Setup listener to handle authorization result event (success or fail)
Line 53: Display the authentication dialog
Line 87: Get nearby venues, an example how to access Foursquare API endpoint. The getNearbyVenue method was defined in FourquareApp.java

FoursquareApp.java

public static final String CALLBACK_URL = "myapp://connect";
private static final String AUTH_URL = "https://foursquare.com/oauth2/authenticate?response_type=code";
private static final String TOKEN_URL = "https://foursquare.com/oauth2/access_token?grant_type=authorization_code";
private static final String API_URL = "https://api.foursquare.com/v2";

Line 1: Replace the CALLBACK_URL with your callback url set before on web settings.
Line 4: API_URL is the root url for Foursquare API endpoint. Do not change this url unless Foursqure make changes on their API url.

public ArrayList<FsqVenue> getNearby(double latitude, double longitude) throws Exception {
		ArrayList<FsqVenue> venueList = new ArrayList<FsqVenue>();

		try {
			String ll 	= String.valueOf(latitude) + "," + String.valueOf(longitude);
			URL url 	= new URL(API_URL + "/venues/search?ll=" + ll + "&oauth_token=" + mAccessToken);

			Log.d(TAG, "Opening URL " + url.toString());

			HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

			urlConnection.setRequestMethod("GET");
			urlConnection.setDoInput(true);
			urlConnection.setDoOutput(true);

			urlConnection.connect();

			String response		= streamToString(urlConnection.getInputStream());
			JSONObject jsonObj 	= (JSONObject) new JSONTokener(response).nextValue();

			JSONArray groups	= (JSONArray) jsonObj.getJSONObject("response").getJSONArray("groups");

			int length			= groups.length();

			if (length > 0) {
				for (int i = 0; i < length; i++) {
					JSONObject group 	= (JSONObject) groups.get(i);
					JSONArray items 	= (JSONArray) group.getJSONArray("items");

					int ilength 		= items.length();

					for (int j = 0; j < ilength; j++) {
						JSONObject item = (JSONObject) items.get(j);

						FsqVenue venue 	= new FsqVenue();

						venue.id 		= item.getString("id");
						venue.name		= item.getString("name");

						JSONObject location = (JSONObject) item.getJSONObject("location");

						Location loc 	= new Location(LocationManager.GPS_PROVIDER);

						loc.setLatitude(Double.valueOf(location.getString("lat")));
						loc.setLongitude(Double.valueOf(location.getString("lng")));

						venue.location	= loc;
						venue.address	= location.getString("address");
						venue.distance	= location.getInt("distance");
						venue.herenow	= item.getJSONObject("hereNow").getInt("count");
						venue.type		= group.getString("type");

						venueList.add(venue);
					}
				}
			}
		} catch (Exception ex) {
			throw ex;
		}

		return venueList;
	}

To access Foursquare API endpoint, use standard HTTPURLConnection class, where the url depends on what endpoint you want to access. Complete list of Foursquare API endpoints can be found here.

Share
Related post:
bottom

79 Responses to “How to Use Foursquare API on Android Application”

  1. Neritae says:

    I have problems when i’ve click on Get Nearby Places button and LogCat this:

    https://lh4.googleusercontent.com/-pIiUO2mUj9Y/Tm-3b9aFmwI/AAAAAAAAAJk/rDJArR6ReSs/s912/asFSDGldgew.jpg

    Could you please give me some hint?

    • lorenz says:

      That means the json response has no ‘address’ field. You can check if the field exists using: jsonObj.isNull(’address’) to prevent parsing error.

      • Andy says:

        So how do you fix this JSON error? Am i just inputting invalid lat/long coordinates, and thus it isn’t returning anything?

        • Andy says:

          For instance I type in
          Long: -84.3566371
          Latitude: 33.7744506
          (Atlanta, GA)

          but it just keeps giving me “failed to load nearby places”, with a similar JSON error as listed above

        • Andy says:

          Errors look pretty much the same as Neritae posted:

          http://andy.dorkfort.com/store/Error%20LogCapture.PNG

          I also tried hooking it up to the actual GPS (you’ll see that in the Logcat too) to feed into the Lat and Long fields, and it gave me the same errors before and after.

          thanks for all your help!

          • Andy says:

            What’s also weird is that if i paste the returned URL from logcat into a browser it gives me correct stuff back like:

            {”meta”:{”code”:200,”errorType”:”deprecated”,”errorDetail”:”This endpoint will stop returning groups in the future. Please use a current version, see http://bit.ly/lZx3NU.“},”notifications”:[{"type":"notificationTray","item":{"unreadCount":0}}],”response”:{”groups”:[{”type”:”nearby”,”name”:”Nearby”,”items”:

  2. Wordked well also. Thank you again for this work.

  3. Andy says:

    Let me thank you because after a ton of searching, i think this is exactly what i was looking for!

  4. Bala says:

    its not working for me.pls help me out!When i login it shows that failed to get access token.

  5. Bala says:

    The above lines are my logcat lines lorenz.pls help me out to get this lorenz

  6. Andy says:

    Ahhh! now i know what you mean, I guess some foursquare entities don’t have an address field. In case anyone wants to know, I put in this line of code in to fix it

    if(!jlocation.isNull(”address”)){
    venue.address = jlocation.getString(”address”);
    }

  7. Guerin Guillaume says:

    Thank you very much for the great code

  8. Failed to get access token :-(
    It looks like the CallBack url is the problem, what should be a valid address to this parameter? Thanks!

    10-23 23:41:58.337: WARN/System.err(372): java.io.FileNotFoundException: https://foursquare.com/oauth2/access_token?grant_type=authorization_code&client_id=XXX&client_secret=XXX&redirect_uri=myapp://connect&code=redirect_uri_mismatch

  9. TheVaan says:

    To fix the distance problem (shows any time “0m”) change line 60 in NearbyAdapter.java from:

    holder.mDistanceTxt.setText(formatDistance(venue.direction));

    to:

    holder.mDistanceTxt.setText(formatDistance(venue.distance));

    Out of this you can delete all parts in the sourcecode that deal with “direction”.

  10. gepeng says:

    om, kenapa aku failed load nearby place trs ya kalo pake ll = -6.168788, 106.726746..
    kira2 kenapa ya om ?
    thx

  11. sparky says:

    nice tutorial
    Thanks for posting

  12. sparky says:

    Nice stuff
    Thanks for posting

  13. Sebastián says:

    Thank you so much for the sample code. It helped me to save a lot of time trying to understand the authentication.

  14. manuzhang says:

    https://github.com/foursquare/android-oauth-example
    This example using ajax seems to be simpler

  15. PUSHPENDRA KUNTAL says:

    Sir, i have done this. now i want to write code for checkin. please help me, how can i write code for checkin of a user.

  16. Partho says:

    Terrific stuff…. Helped a lot… Thanks

  17. Nick Margaritis says:

    Hi,

    i used your code and i get a message invalid_request…

    The only thing i changed was the client_id and client_secret

    https://foursquare.com/oauth2/authenticate?response_type=code&client_id=XXXX&redircet_uri=myapp://connect

  18. vennila vaithi says:

    Hi Lorenz,
    I tried your application , But am getting access token token failed and failed to load NearByValues, I only changed the Client_id and Client_secret and callback url . I got the following error in my logCat

    03-30 15:31:08.382: W/System.err(516): java.io.IOException: Received authentication challenge is null
    03-30 15:31:08.382: W/System.err(516): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.java:1694)
    03-30 15:31:08.391: W/System.err(516): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.java:1649)
    03-30 15:31:08.391: W/System.err(516): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1153)
    03-30 15:31:08.391: W/System.err(516): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:253)
    03-30 15:31:08.391: W/System.err(516): at net.londatiga.fsq.FoursquareApp.getNearby(FoursquareApp.java:214)
    03-30 15:31:08.391: W/System.err(516): at net.londatiga.fsq.Main$5.run(Main.java:121)

    pls give me whats wrong in this?

  19. Gnaesh says:

    Awesome stuff…

  20. Dhaval says:

    hi,

    i am use your code in my app. but i got error when redirect after login.

    error like “you have not permission to open this page”

  21. giles ian says:

    what changes do i need to make in the above project if i dont have website … i only have android app

  22. victor yew says:

    Hi Lorenz,

    I’ve got the access token successfully BUT I am connected as a NULL. How do I get self username? Thx

  23. danzil says:

    I have the same problem as victor, connected as null, and failed to get the file in the logcat, how to solve this problem, Please help Lorenz. Thanks for the great work.

  24. Eray says:

    found Connected as null solution.

    add &v=20120801 to end of connection parameter
    for more details https://developer.foursquare.com/overview/versioning

    • Eray says:

      and change connection type as below

      RL url = new URL(API_URL + “/users/self?oauth_token=”
      + mAccessToken + “&v=201208201″);

      Log.d(TAG, “Opening URL ” + url.toString());

      HttpGet httpRequest = null;

      httpRequest = new HttpGet(url.toURI());
      HttpClient httpclient = new DefaultHttpClient();
      HttpResponse httpresponse = (HttpResponse) httpclient
      .execute(httpRequest);

      HttpEntity entity = httpresponse.getEntity();
      BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(
      entity);
      InputStream input = bufHttpEntity.getContent();

      String response = streamToString(input);

    • lorenz says:

      Hi Eray,

      Thanks for the solution, currently thats not a mandatory, you can still use the API without versioning.

      Not passing the v parameter will currently return the oldest version of the API. In the future, the default will be to use the most recent API (instead of current default, which is to use the oldest API). Over time, we will phase out support for legacy behavior.

      But it is recommended to use versioning for compatibility in the future API update. The real problem with my codes was in HttpConnection (see my answer to danzil). The solution is to remove the “urlConnection.setDoOutput(true);” line or replace the HttpConnection with HttpClient for making connection with http as you described in your solution code..

  25. Eray says:

    Dear Lorenz,

    herenow parameter is no longer returned from API.
    There are :

    “stats”: {
    “checkinsCount”: 285,
    “usersCount”: 181,
    “tipCount”: 1
    },

    and
    “beenHere”: {
    “count”: 0
    },

  26. anonymous says:

    Halo Om Lorenz saya mau tanya donk.
    Kok setiap get nearby places failed mulu y?
    ni logcat ny om :

    09-07 16:35:21.619: W/System.err(23522): org.json.JSONException: No value for groups
    09-07 16:35:21.629: W/System.err(23522): at org.json.JSONObject.get(JSONObject.java:354)
    09-07 16:35:21.629: W/System.err(23522): at org.json.JSONObject.getJSONArray(JSONObject.java:544)
    09-07 16:35:21.639: W/System.err(23522): at net.londatiga.fsq.FoursquareApp.getNearby(FoursquareApp.java:221)
    09-07 16:35:21.639: W/System.err(23522): at net.londatiga.fsq.Main$5.run(Main.java:122)
    09-07 16:35:21.759: W/asset(23522): deep redirect failure from 0×01030046 => 0×02060015, defStyleAttr=0×01010084, defStyleRes=0×01030022, style=0×00000000

    mohon bantuannya om. :D

  27. anonymous says:

    09-07 16:35:21.619: W/System.err(23522): org.json.JSONException: No value for groups
    09-07 16:35:21.629: W/System.err(23522): at org.json.JSONObject.get(JSONObject.java:354)
    09-07 16:35:21.629: W/System.err(23522): at org.json.JSONObject.getJSONArray(JSONObject.java:544)
    09-07 16:35:21.639: W/System.err(23522): at net.londatiga.fsq.FoursquareApp.getNearby(FoursquareApp.java:221)
    09-07 16:35:21.639: W/System.err(23522): at net.londatiga.fsq.Main$5.run(Main.java:122)
    09-07 16:35:21.759: W/asset(23522): deep redirect failure from 0×01030046 => 0×02060015, defStyleAttr=0×01010084, defStyleRes=0×01030022, style=0×00000000

  28. Androider says:

    Hi Lorenz, first thanks a lot for posting this. It helped me a lot. But I got some kind of an error in the pop up layout. It says :-
    Connecting failed
    This app has a configuration problem and was unable to connect to your foursquare account.

    By the I gave internet permission on the android manifest file.

    Please help me.

    Thank you

  29. Donald Burns says:

    Freind,

    Is it possible to create my own app that uses four squares data and be available to sell on Google Play?

  30. Grace says:

    Hi
    I am trying to register as new consumer with the link posted but it’s not working. Can any one please tell me the stepsto get my ClientID and Client Secret.
    I am not able to locate it on Foursquare api website.

    Thanks alot

  31. Mitesh says:

    I am getting Authorization failed Error.. Please Help..

  32. Mitesh says:

    I am getting Authorization failed error. Please help

  33. I have problems when i’ve click on Get Nearby Places button and LogCat this:https://lh4.googleusercontent.com/-pIiUO2mUj9Y/Tm-3b9aFmwI/AAAAAAAAAJk/rDJArR6ReSs/s912/asFSDGldgew.jpgCould you please give me some hint?

  34. yash says:

    hello all,
    at this point they(foursquare have removed firstname,lasname detail on json,and also removed “groups” field . )
    So when u start app please debug on eclipse or any IDE and then try to hit URL on webbrowser u will see json response and check that response.

  35. esquiter says:

    hello, I tried to run this example, but not JSON comes complete, when I run the url in the browser works normally.

    what’s going?

  36. Claudia Bauger says:

    Hey hi,
    I has been set all the required value as you said.But i don’t know, i’m getting “Authorization failed” Exception.
    Required value:-
    1.Client ID
    2.Secrete key
    3.CALLBACK URI :-( https://www.jhakas.com/redirect_uri)

    Please your help will be very appreciable

    thank you in advance

  37. Claudia Bauger says:

    Hey hi,
    I has been set the required value as you said.But i don’t know, I’m getting “Authorization failed ” message.

    Required changes:
    1.Client ID
    2.Secrete key
    3.Call back URI(https://www.jhakas.com/redirect_uri)

    Please you help will be appreciable

    thank you

  38. Claudia Bauger says:

    Hey hi ,
    First of all i just want to say thank for your great work. this is claudia again with new error, Last one error, some how I has been solved.

    Now when the get the palces…It gives a JSONException “No value for groups ” What does that means…..

    Please help me out

    Thanks

  39. Undang says:

    Om, help me ni ko failed to get nearby places terus ni di logcat nya “org.json.JSONException: No value for groups” ..
    gimana ya ?

  40. Undang says:

    Om, help me ni selalu “failed to load nearby places”,

    error di logcatnya begini “org.json.JSONException: No value for groups”.

    help me donk

  41. ankit sharma says:

    hi,

    I am unable to get the near by places as it says ‘failed to load the nearby places” with the following logcat :

    04-19 10:31:10.830: D/FoursquareApi(10756): Opening URL https://api.foursquare.com/v2/venues/search?ll=43.89765,77.123455&oauth_token=H0SURUVPG2DKXLSSTRBLBQ2OT4UKMQDAOFFBOVUJSZYT0R0C&v=20130419
    04-19 10:31:13.342: W/System.err(10756): org.json.JSONException: No value for groups
    04-19 10:31:13.342: W/System.err(10756): at org.json.JSONObject.get(JSONObject.java:354)
    04-19 10:31:13.342: W/System.err(10756): at org.json.JSONObject.getJSONArray(JSONObject.java:544)
    04-19 10:31:13.342: W/System.err(10756): at com.example.nearbyplaces.FoursquareApp.getNearby(FoursquareApp.java:217)
    04-19 10:31:13.352: W/System.err(10756): at com.example.nearbyplaces.MainActivity$5.run(MainActivity.java:108)

  42. PUSHPENDRA KUNTAL says:

    Sir please help me to find out code for check in at a place.

  43. lorenz says:

    Hi danzil, sorry for the late reply.

    The problem was in HttpURLConnection (if you use SDK 4.0/ICS or newer). Since ICS, if you choose to set the setDoOutput() to “true”, the HTTP method would be POST even if you set the setRequestMethod() to “GET”. So in FoursquareApp.java, in method fetchUserName (https://github.com/lorensiuswlt/AndroidFoursquare/blob/master/src/net/londatiga/fsq/FoursquareApp.java), comment or delete the row

    “urlConnection.setDoOutput(true);”

    Hope it helps.

Leave a Reply

 
bottom