Once you figured out how OAuth works, you might ask yourself how this principle works from within a native Android app. It’s actually easier then expected at first. There exist some libraries that can make our life somehow easier, but I decided not to use any of them and to do everything from scratch.
This is the OAuth workflow for Foursquare:
- A call to the Foursquare server is made with the client id and a redirect URL (has to be in a browser)
- The user accepts the access request of the application
- Foursquare calls the redirect URL with special code as parameter
- The Foursquare server has to be called again with the client id, client secret, the code and the redirect URL (not in the browser anymore)
- Foursquare returns now the access token which has to be saved by the app
- Further calls to the Foursquare API can be made with the token
The only problem in this workflow is how we can make the first call in the browser and then return to our app.
OK, we’re going to register out app first as an OAuth Consumer at Foursquare. Define the Callback URL as “simontest-android-app://”. You can do so here.
Now, we create a new Android project and give it the INTERNET permission.
Then open the Manifest file and add the following filter to the <application> tag:
<application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".LoginTest" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- Add this filter --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="simontest-android-app" /> </intent-filter> </activity> </application>
This maps the schema “simontest-android-app” to this activity.
Now it’s time to start the coding. Add a button or something to your UI and add a click listener to it, which calls this method:
private void loginToForsquare() {
// Call the webbrowser with the Foursquare OAuth login URL
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(
Uri.parse(
"https://foursquare.com/oauth2/authenticate" +
"?client_id=" +CLIENT_ID +
"&response_type=code" +
"&redirect_uri=simontest-android-app://"));
startActivity(intent);
}
This will open the browser where the user can accept or deny our app to access his Foursquare data. After that the browser will automatically be redirected to the Callback URL “simontest-android-app://” which we have previously mapped to our activity. The activity will be called and we can check for the expected parameter in the onResume() method:
public void onResume() {
super.onResume();
// extract the OAUTH access token if it exists
Uri uri = this.getIntent().getData();
if(uri != null) {
String code = null;
// Check if ther is a parameter called "code"
if((code = uri.getQueryParameter("code")) != null){
try {
// Call Foursquare again to get the access token
JSONObject tokenJson = executeHttpGet(
"https://foursquare.com/oauth2/access_token" +
"?client_id=" + CLIENT_ID +
"&client_secret=" + CLIENT_SECRET +
"&grant_type=authorization_code" +
"&redirect_uri=simontest-android-app://" +
"&code=" + code);
String token = tokenJson.getString("access_token");
// TODO save token
// Get userdata of myself
JSONObject userJson = executeHttpGet(
"https://api.foursquare.com/v2/" +
"users/self" +
"?oauth_token=" +token);
// Get return code
int returnCode = Integer.parseInt(userJson.getJSONObject("meta").getString("code"));
// 200 = OK
if(returnCode == 200){
// output data
Log.i("LoginTest", userJson.getJSONObject("response").getJSONObject("user").toString());
}else{
Toast.makeText(this, "Wrong return code: " +code, Toast.LENGTH_SHORT).show();
}
} catch (Exception exp) {
Log.e("LoginTest", "Login to Foursquare failed", exp);
}
}else if((code = uri.getQueryParameter("error")) != null){
Toast.makeText(this, code, Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "Unknown login error", Toast.LENGTH_SHORT).show();
}
}
}
// Calls a URI and returns the answer as a JSON object
private JSONObject executeHttpGet(String uri) throws Exception{
HttpGet req = new HttpGet(uri);
HttpClient client = new DefaultHttpClient();
HttpResponse resLogin = client.execute(req);
BufferedReader r = new BufferedReader(
new InputStreamReader(resLogin.getEntity()
.getContent()));
StringBuilder sb = new StringBuilder();
String s = null;
while ((s = r.readLine()) != null) {
sb.append(s);
}
return new JSONObject(sb.toString());
}
And that is already everything. You just might wanna save the token after you’ve got it so you don’t have to login to Foursquare the next time the user starts your app.
Happy Coding!

8:14 pm, June 13, 2011geykel /
Hello Simon,
Thank you for this great post which helped me a lot to understand how OAuth v2.0 works and how to integrate it to an Android app. I got a question though, I was testing some code that I wrote using your ideas here and everything is working great but I want to change one thing and I want to see if you can give me some directions. My app basically sign in an user to 4sq and then retrieve all the nearby venues, the first time the user sign in, 4sq ask me to authorize my app, that’s ok, but next time the user sign in, the app open the browser again (because we are calling an intent for doing that) this time of course 4sq don’t ask me to authorize the app because we did that already and just call our custom redirect-uri and give us the access_token… so, what I wanted to ask you is, is there any other way of doing this without open the android browser? at least for every sign in after the first one? which is the one where the user authorize the app (we need the browser for that first sign in)…
Sorry for this long comment
9:13 pm, June 13, 2011Simon /
Hi
there is no need to open the browser again. you can just store the OAuth token in the app after the first login and reuse it the next time.
Simon
6:13 pm, June 20, 2011Rafael Ramos /
Hi Simon,
Nice tutorial!
I was testing your piece of code but right after I give access to my app on foursquare via browser, I’m being redirected to a page that foursquare cannot handle. It says ‘we couldn’t find the page you’re looking for’. And then I never get the token nor my callback url is called.
Basically, the url for this ‘broken’ page is: https://foursquare.com/oauth2/mycallback?code=mycode.
Where, ‘mycallback’ is my callback url (ending with ://) and ‘mycode’ is actually my code.
Do you have any idea of what might be happening?
Rafael
12:33 pm, June 21, 2011Simon /
Hi Rafael
oauth works in 2 steps: first you need to authorize your app, then you get the access token.
1. https://foursquare.com/oauth2/authenticate?client_id={YOUR_CLIENT_ID}&response_type=code&redirect_uri={YOUR_DEFINED_SCHEME}
2. https://foursquare.com/oauth2/access_token?client_id={YOUR_CLIENT_ID}&client_secret={YOUR_CLIENT_SECRET}&grant_type=authorization_code&redirect_uri={YOUR_DEFINED_SCHEME}&code={CODE_YOU_VE_GOT_IN_STEP_1}
where {YOUR_DEFINED_SCHEME} can actually be anything (“simontest-android-app://” in case of my example)
Simon
5:01 pm, October 23, 2011Márcio Martins /
Hi!
OAuth Consumer Registration doesn’t accept the simontest-android-app:// pattern anymore, returning the following error: Your URL needs a body too (just http:// won’t work).
Can you advise? Thanks!
2:27 pm, October 24, 2011Simon /
i have never seen this error on my side, nor does google return anything when searching for it. you might try to add a path to your url (like simontest-android-app://mypath), but my guess is that the problem lies somewhere else.
3:29 am, January 12, 2012suraj g sakhardane /
Its a wonderful and very helpful post.1 question i was having is that we can make response_type=token in the the following query and get the access token directly (in which case access token is appended to the callback url/registered redirect url ) then why we need to do a 2 step process?
https://foursquare.com/oauth2/authenticate?client_id={YOUR_CLIENT_ID}&response_type=code&redirect_uri={YOUR_DEFINED_SCHEME}
ie
https://foursquare.com/oauth2/authenticate?client_id={YOUR_CLIENT_ID}&response_type=token&redirect_uri={CALL_BACK_URL}
gives
CALL_BACK_URL#access_token=ACCESS_TOKEN
I tried this in the browser n it working.It is asking for authentication and later redirecting to CALL_BACK_URL with access token appended to it!
9:33 pm, January 12, 2012Simon /
the 2 step process i describe is according the foursquare documentation. there might be other undocumented ways to achieve the same, but there is a risk that this functionality could change in the future.
for more information, please see the official documentation: https://developer.foursquare.com/overview/auth