Home > OAuth Signpost > Implementing the OAuth flow in Android

Implementing the OAuth flow in Android

In this post, I’ll be showing you how to use the OAuth signpost library in an Android application. We’ll create a simple application that fetches your Google Contacts using the Google Contacts API, and display the contact names on the screen.
We’ll focus on using the Signpost API in an Android runtime, and implementing the OAuth workflow from the first step (requesting a request token) till the final API call with our access token. We’ll glue the entire OAuth workflow together in our Android application, using different techniques offered by the Android platform. As you can see from the screenshot below, it’s not the most aesthetically pleasing application, but it gets the job done.
oauth-android-logo

Application Overview

If all goes well, our application should look like this :

As our application needs to fetch user data from Google, the user needs to authorize the application in order to fetch his data on his behalf. If the user doesn’t authorize access, the application will not be able to fetch our contacts, and will throw the following exception :

As stated before, in order to avoid this error, we need to authorize the application to fetch this data (act on our behalf), and this is where OAuth comes in the picture. The home screen contains a “Launch OAuth Flow” button that will trigger the OAuth flow we discussed in our OAuth overview post.

When clicking on this button, you’ll be redirected to the google accounts page, where you will be prompted to login to your account (if you haven’t already).

After a succesfull login, Google will state that an application is requesting access to your Google Contacts, and will ask you to authorize or grant this access.

When the user grants access, the application will make an API call to Google, and display the contacts on the screen.

Application internals

Start the OAuth Dance

When we click on the Launch OAuth Flow button, we’re basically launching an activity called PrepareRequestTokenActivity that will be responsible for retrieving the request token.

        Button launchOauth = (Button) findViewById(R.id.btn_launch_oauth);
        Button clearCredentials = (Button) findViewById(R.id.btn_clear_credentials);

        launchOauth.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	startActivity(new Intent().setClass(v.getContext(), PrepareRequestTokenActivity.class));
            }
        });

Retrieve Request Token

The PrepareRequestTokenActivity activity will do the following :

  • Prepare the OAuthConsumer with the consumer key and consumer secret
  • Prepare the OAuthProvider by specifying the 3 OAuth endpoints (request , authorize , access)
  • Launch the OAuthRequestTokenTask, responsible for fetching the request token.

This should all look familiar, as we did the exact same thing in the commandline example.

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
    	try {
        	System.setProperty("debug", "true");
    	      this.consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
    	        this.provider = new CommonsHttpOAuthProvider(
    	        		Constants.REQUEST_URL  + "?scope=" + URLEncoder.encode(Constants.SCOPE, Constants.ENCODING),
    	        		Constants.ACCESS_URL,
    	        		Constants.AUTHORIZE_URL);
        	} catch (Exception e) {
        		Log.e(TAG, "Error creating consumer / provider",e);
    		}

        Log.i(TAG, "Starting task to retrieve request token.");
		new OAuthRequestTokenTask(this,consumer,provider).execute();
	}

The OAuthRequestTokenTask calls the retrieveRequestToken method on the OAuthProvider. If might recall from our previous hands on example with Signpost that in this step, the Signpost library will fetch a request token from Google, and return the URL that is required to authorize this request token. That authorization URL will then be displayed in a browser, ready for the user to authorize the request.

	/**
	 *
	 * Retrieve the OAuth Request Token and present a browser to the user to authorize the token.
	 *
	 */
	@Override
	protected Void doInBackground(Void... params) {

		try {
			Log.i(TAG, "Retrieving request token from Google servers");
			final String url = provider.retrieveRequestToken(consumer, Constants.OAUTH_CALLBACK_URL);
			Log.i(TAG, "Popping a browser with the authorize URL : " + url);
			Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
			context.startActivity(intent);

		} catch (Exception e) {
			Log.e(TAG, "Error during OAUth retrieve request token", e);
		}

		return null;
	}

So at this point the signpost library has capured the requestToken

Authorize the request token

At this point, the user should login to Google (if not already done), and authorize the request. As you can see from the code snippet above, when requesting the request token, we also provide a callback URL (provider.retrieveRequestToken(consumer, Constants.OAUTH_CALLBACK_URL)).

This callback URL is defined like this x-oauthflow://callback.

Obviously, we want our application to react to this callback, as the URL will contain our authorized token (oauth_token) and the oauth_verifier required to retrieve the access token .

When the user grants his permission, the callback URL is received in the browser, we some kind of interceptor in our application, so an action can be triggered to interpret this callback URL, and extract the oauth_token and oauth_verifier.

This interceptor is implemented on the PrepareRequestTokenActivity using the onNewIntent method.

	/**
	 * Called when the OAuthRequestTokenTask finishes (user has authorized the request token).
	 * The callback URL will be intercepted here.
	 */
	@Override
	public void onNewIntent(Intent intent) {
		super.onNewIntent(intent);
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		final Uri uri = intent.getData();
		if (uri != null && uri.getScheme().equals(Constants.OAUTH_CALLBACK_SCHEME)) {
			Log.i(TAG, "Callback received : " + uri);
			Log.i(TAG, "Retrieving Access Token");
			new RetrieveAccessTokenTask(this,consumer,provider,prefs).execute(uri);
			finish();
		}
	}

The fact that the onNewIntent method is called is a result of the manifest , where the activity is configured with a singleTask launchMode. It also has an intent filter to react to our callback url.

Each element in an intent filter can specify a URI and a data type. Here we’re only interested in the URI. There are separate attributes — scheme, host, port, and path — for each part of the URI (scheme://host:port/path) that we can filter against. In our case, we filter on the scheme and the host, as that should be sufficient to identify our callback URL. Remember that the callback URL was defined like this x-oauthflow://callback.

		<activity android:name=".PrepareRequestTokenActivity" android:launchMode="singleTask">>
			<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="x-oauthflow" android:host="callback" />
			</intent-filter>
		</activity>

Retrieving the access token

Because our PrepareRequestTokenActivity has a singleTask launchMode AND an intent filter on our callback was specified, the onNewIntent method will be called on our activity as soon as our callback URL is received in the browser. This is the perfect place to continue the OAuth flow. At this point, the user has authorized our request. Using the oauth_verifier, we can now retrieve the access token that will be required to make the API calls. Retrieving the access token is handled by the RetrieveAccessTokenTask

	/**
	 * Retrieve the oauth_verifier, and store the oauth and oauth_token_secret
	 * for future API calls.
	 */
	@Override
	protected Void doInBackground(Uri...params) {
		final Uri uri = params[0];

		final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

		try {
			provider.retrieveAccessToken(consumer, oauth_verifier);

			final Editor edit = prefs.edit();
			edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
			edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
			edit.commit();

			String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
			String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");

			consumer.setTokenWithSecret(token, secret);
			context.startActivity(new Intent(context,OAuthFlowApp.class));

			Log.i(TAG, "OAUTH STAGE TWO OK!");

		} catch (Exception e) {
			Log.e(TAG, "OAUTH STAGE TWO ERROR", e);
		}

		return null;
	}
 

What we’re seein here is that the Signpost library is retrieving the access token, and storing it in our shared preferences. Now that we have the acccess token , and token secret, we start our initial activity again.

In our initial activity, we’re doing an API call to the Google Contacts API, and let our OAuthConsumer sign the request :

	private String doGet(String url,OAuthConsumer consumer) throws Exception {
		DefaultHttpClient httpclient = new DefaultHttpClient();
    	HttpGet request = new HttpGet(url);
    	Log.i(TAG,"Requesting URL : " + url);
    	consumer.sign(request);
    	HttpResponse response = httpclient.execute(request);
    	Log.i(TAG,"Statusline : " + response.getStatusLine());
    	InputStream data = response.getEntity().getContent();
    	BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(data));
        String responeLine;
        StringBuilder responseBuilder = new StringBuilder();
        while ((responeLine = bufferedReader.readLine()) != null) {
        	responseBuilder.append(responeLine);
        }
        Log.i(TAG,"Response : " + responseBuilder.toString());
        return responseBuilder.toString();
	}

The OAuthConsumer can be re-created at any time using the following code. Keep in mind that Signpost objects (consumer / provider) are very lightweight, and there is little to no overhead involved in re-creating them. The code below fetches our access token and token secret from the preferences (that were stored in the RetrieveAccessTokenTask execution), and re-creates our OAuthConsumer that we’ll use to sign our requests.

	private OAuthConsumer getConsumer(SharedPreferences prefs) {
		String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
		String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
		OAuthConsumer consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
		consumer.setTokenWithSecret(token, secret);
		return consumer;
	}

Source code for Implementing the OAuth flow in Android has been uploaded to Github.

References :

  1. John
    January 19th, 2011 at 11:08 | #1

    hi…

    I am new to android development.I am not understanding, how to prepare OAuthConsumer & OAuthProvider and how can I get my consumer key, consumer secret.

    And one more thing, I am getting errors (like Create class ‘OAuth’; Create class ‘OAuthConsumer ‘ & Create class ‘OAuthProvider’) while running the Source code(which is provided here)
    Can you please help me on this.Its urgent.

    Thanks in advance.

  2. admin
    January 19th, 2011 at 11:35 | #2

    @John What exactly is the problem you’re getting ? Are you executing this code from Eclipse ? For an overview on OAuth (and how to retrieve a consumer key and consumer secret) check out Google OAuth Overview. Also, the code in Github works out of the box providing you’ve followed the Integrating maven in your Android Eclipse projects steps.

  3. Guy Mac
    January 22nd, 2011 at 18:23 | #3

    This is great, thanks a lot. I would like to see a real-world Android app work-flow, I mean I don’t see any apps with ‘launch oath flow’ or ‘clear credentials’ buttons or menu items, so how do they do it?

  4. admin
    January 23rd, 2011 at 12:01 | #4

    @Guy Mac
    Typically, the “Laucn OAuth flow” would be implemented when the application has determined that either no access token, or an invalid access token was available to the application. This can be the case when the application is first opened, when the access token became invalid, or when the user decided to revoke access to the token. In these cases, the OAuth flow needs to be launched by the app allowing the user to login, approve the authorization, and get an access token in the app. So indeed, this typically isn’t done through a button, but launched automatically via internal logic in the app. The “Clear credentials” button would typically be used for log-off functionality (deleting the access token, forcing the user to login again).

  5. February 21st, 2011 at 05:51 | #5

    Hi,

    I’m really appreciate your work for writing this article. Very useful.
    However, I got a FC when I used AsyncTask to do something in background, and don’t know why. As a result, I move the code in two subclasses of AsyncTask to the PrepareRequestTokenActivity(named O). My source code is pasted in google docs below. Would you mind to take a look at it? I’m a newbie of Android, and I add the steps marking the control flow.

    Thanks in advance. Cheers
    Tom

    https://docs.google.com/document/pub?id=1HtTy2RHvFKLFiHcKz0dv8XJR058FOJcYyJjlURv6C2Y

    • admin
      February 22nd, 2011 at 16:12 | #6

      Are you still getting the Force Close window ? If so, can you post the stacktrace ?

  6. Tony D
    February 27th, 2011 at 21:32 | #7

    Great example. I’m a bit confused as where to store the Consumer Secret. Is it possible for an installed Android App to store the oauth_consumer_secret in a more secure manner than just embedding it in the binary code where it can be decompiled and compromised? Does Android Preferences fit this purpose? Basically, if I’m rolling out an installed mobile app, where do I store the consumer key/secret (other than than in the code itself) ?

    • admin
      February 28th, 2011 at 17:04 | #8

      I had the exact same question and I posted it on stackoverflow … Feel free to have a look at the detailed answer.

  7. Tony D
    February 28th, 2011 at 20:15 | #9

    On your stackflow blog post you’ve said: ” do the proxy-ing and keep the secret on the webserver where I’m fairly sure it would not get compromised”

    How are you planning on securing the consumer secrets on your web server against rogue clients? Will the client needs to be authenticated to your web server? If so, these “authenication_tokens” will still need to be stored on the Client device, so we’re back to the first issue.

    • admin
      March 1st, 2011 at 21:22 | #10

      Yes, but only in this case they’re not packaged with the app anymore. Authentication from the Android app to the webserver is tricky, and for me was just not worth the effort. (it also adds an additional integration point to the app that needs to be up & running)
      I finally ended up just embedding it in the application.

  8. LA
    March 15th, 2011 at 20:20 | #11

    Many thanks for this article.
    I am new to Android development also and my app also crashes when I try to authorize with OAuth – authorization button is added to the preference screen in my case.
    Could you please help me to understand what is wrong in my code? The code is uploaded to http://rapidshare.com/files/452720582/app.zip.

    Thank you in advance!

  9. LA
    March 15th, 2011 at 20:59 | #12

    @LA
    ok, found the issue ))

  10. LA
    March 18th, 2011 at 19:39 | #13

    Hi, I am still trying to implement OAuth in my application, but with no success.
    Here is the log:

    03-18 19:39:39.479: INFO/com.ecs.android.oauth.OAuthRequestTokenTask(2090): Retrieving request token from the server
    03-18 19:39:44.308: INFO/System.out(2090): [SIGNPOST] SBS: POST&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dx-oauthflow%253A%252F%252Fcallback%26oauth_consumer_key%3Danonymous%26oauth_nonce%3D-5649524238968046409%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1300477184%26oauth_version%3D1.0
    03-18 19:39:44.518: INFO/System.out(2090): [SIGNPOST] signature: k3wd2hJ624VMBbkBAF0jPTEzrpw=
    03-18 19:39:44.588: INFO/System.out(2090): [SIGNPOST] Auth header: OAuth oauth_callback=”x-oauthflow%3A%2F%2Fcallback”, oauth_consumer_key=”anonymous”, oauth_version=”1.0″, oauth_signature_method=”HMAC-SHA1″, oauth_timestamp=”1300477184″, oauth_nonce=”-5649524238968046409″, oauth_signature=”k3wd2hJ624VMBbkBAF0jPTEzrpw%3D”
    03-18 19:39:44.608: INFO/System.out(2090): [SIGNPOST] Request URL: https://www.google.com/accounts/OAuthGetRequestToken
    03-18 19:39:51.687: DEBUG/dalvikvm(2090): GC freed 5661 objects / 340760 bytes in 200ms
    03-18 19:39:52.337: INFO/global(2090): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
    03-18 19:40:59.327: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(2090): Error during OAuth retrieve request token
    03-18 19:40:59.327: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(2090): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: Service provider responded in error: 400 (Bad Request)

    What can be wrong in my code?

  11. LA
    March 18th, 2011 at 20:01 | #14

    ok, found the issue again ))
    please remove my messages.

    Btw, could you please describe how OAuth authorization can be done if server doesn’t support callbacks (i.e. authorization with usage of pin).

  12. piyush palod
    March 22nd, 2011 at 13:12 | #15

    Thanks a ton… it helps a lot. gr8 work

    cheers
    Piyush Palod

  13. LA
    March 26th, 2011 at 09:00 | #16

    Got another question ;)
    I start OAuth flow from Preferences screen. Once authorization is successfully completed, I need to disable Sign In button there. I have special function in Preferences class, which does it:

    public void enableDisableSignInOut() {
    Preference signinPref = (Preference) findPreference(“pref_account_sign_in”);
    Preference signoutPref = (Preference) findPreference(“pref_account_sign_out”);
    // disable Sign In button if already authorized
    // and enable Sign Out
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    String token = prefs.getString(OAuth.OAUTH_TOKEN, “”);
    String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, “”);
    Log.i(“”,”secret: “+secret);
    signinPref.setEnabled(secret.equals(“”));
    signoutPref.setEnabled(!signinPref.isEnabled());
    }

    How can I call it from RetrieveAccessTokenTask / doInBackground? Probably, I should call it from onPostExecute?
    Or, alternatively I think I can update Preferences activity (the same function is called in onCreate), but how can I do it? Found recreate() function, but it is not clear for me how to use it.

  14. LA
    April 6th, 2011 at 20:26 | #17

    Could you please help me to understand what kind of ProGuard settings for oauth-signpost library should be used?

    http://stackoverflow.com/questions/5572426/what-kind-of-proguard-settings-for-oauth-signpost-library-should-be-used

  15. LA
    April 7th, 2011 at 08:31 | #18

    Has anyone tried to use this with Miren browser? Looks like it doesn’t re-direct to x-oauthflow://. What can be done to fix it?

  16. Vishal
    July 2nd, 2011 at 12:30 | #19

    Hey i want the same for my domain name which is done with google.com it as follows

    https://www.google.com/a/saggezza.com

    This is with google apps account

    if you could check the link above. i wanted to extract the details contacts etc etc for my company. please could you help with the same as you have done it for gmail accounts. I wanted the same with the domain name above accounts.

  17. Alexia
    July 11th, 2011 at 04:39 | #20

    Hi,

    I am developing an android application that needs to access user data from a site that supports OAuth 1.0 without callbacks. I’m using the signpost libraries signpost-core-1.2.jar and signpost-commonshttp4-1.2.1.1.jar.

    Because of the type of client I’m developing (this is academic research and the site I’m connecting to is developed internally – we use consent forms for user approval), users will not need to authorize the website to access their data.

    Therefore, with the way standard OAuth works for Android, I’m not able to retrieve the access token because the site I’m trying to connect to doesn’t require the user to specify a verification code. To get the access token from signpost, it seems I need to provide some type of verification code.

    MY QUESTION: Is there a way to bypass this step and still obtain an access token?

    Otherwise, I get the message “Authorization failed (server replied with a 401)”. I’ve set up/registered my client.

    I have been working on this problem for a couple of days. I would appreciate any help or workarounds. Thanks.

  18. TR
    July 12th, 2011 at 13:39 | #21

    Hi, I tried duplicating the steps and code provided from this tutorial. I get the following error in logcat. I am using the signpost 1.2.1.1 library and 1.2 core library. Is there an issue with the signpost libraries I’m using? Any help is appreciated, I’ve been stuck with implementing OAuth on Android overall but I wanted to try a working example first. Thanks.

    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): FATAL EXCEPTION: main
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): java.lang.AbstractMethodError: abstract method not implemented
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:66)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at cmu.test.signpostandroid.PrepareRequestTokenActivity.onCreate(PrepareRequestTokenActivity.java:41)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.os.Handler.dispatchMessage(Handler.java:99)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.os.Looper.loop(Looper.java:123)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at android.app.ActivityThread.main(ActivityThread.java:4627)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at java.lang.reflect.Method.invokeNative(Native Method)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at java.lang.reflect.Method.invoke(Method.java:521)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    07-12 09:32:14.951: ERROR/AndroidRuntime(2749): at dalvik.system.NativeStart.main(Native Method)

    • admin
      July 16th, 2011 at 18:01 | #22

      Seems like you have conflicting version of the signpost library. Is it possible you’re mixing versions ? Signpost also has a commonshttp extension. You need to make sure both signpost and signpost-commonshttp4 are the same version.

  19. sat
    September 5th, 2011 at 10:53 | #23

    Hi,

    I am trying oAuthFlow for youtube oAuth authentication,
    using scope as http://gdata.youtube.com
    and API request url as : http://gdata.youtube.com/feeds/api/videos/

    It asks for authentication , but after authentication, callback is not called, instead logs in directly in the browser and stays in browser.
    Is authentication flow different for YouTube ?

  20. red
    October 7th, 2011 at 11:47 | #24

    NoClassDefFound error. Hello, i cannot run this example because I always get

    java.lang.NoClassDefFoundError: oauth.signpost.commonshttp.CommonsHttpOAuthConsumer

    I don’t understand why this would be happen since the dependency is on the pom.xml file and has scope compile. The jar file also exists in the local repository so has been retrieved.

  21. senchi
    November 5th, 2011 at 01:47 | #25

    Hi,

    Well, I have the same problem with YouTube oauth.. instead returning to callback, the browser redirects me to youtube home (or so) and pops up the message “Invalid Parameters”.

    Is there a workaround?

    Thanks

  22. vishal
    November 21st, 2011 at 09:59 | #26

    this works fine on 3.2.1.. why not on 3.2?
    any idea?
    got error at
    >
    final String url =provider.retrieveRequestToken(consumer, Constants.OAUTH_CALLBACK_URL);

    oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: Service provider responded in error: 400 (Bad Request)
    I can see this only on Motorola xoom 3.2 not on motorola 3.2.1 look like signpost library issue…

    11-22 02:04:51.660: INFO/ActivityManager(141): Starting: Intent { cmp=com.ecs.android.oauth/.PrepareRequestTokenActivity } from pid 6296
    11-22 02:04:51.680: INFO/com.ecs.android.oauth.PrepareRequestTokenActivity(6296): Starting task to retrieve request token.
    11-22 02:04:51.680: INFO/com.ecs.android.oauth.OAuthRequestTokenTask(6296): Retrieving request token from Google servers
    11-22 02:04:51.740: DEBUG/TabletStatusBar(193): lights on
    11-22 02:04:51.990: INFO/ActivityManager(141): Displayed com.ecs.android.oauth/.PrepareRequestTokenActivity: +327ms
    11-22 02:04:57.050: DEBUG/dalvikvm(3096): GC_EXPLICIT freed 238K, 5% free 6709K/7047K, paused 7ms+2ms
    11-22 02:04:58.860: INFO/System.out(6296): [SIGNPOST] SBS: POST&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dx-oauthflow%253A%252F%252Fcallback%26oauth_consumer_key%3Danonymous%26oauth_nonce%3D-8718158770338538733%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1321927498%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F
    11-22 02:04:58.870: INFO/System.out(6296): [SIGNPOST] signature: SoAGPsRU48uRE0B49p4UKTiEK9c=
    11-22 02:04:58.880: INFO/System.out(6296): [SIGNPOST] Auth header: OAuth oauth_callback=”x-oauthflow%3A%2F%2Fcallback”, oauth_consumer_key=”anonymous”, oauth_version=”1.0″, oauth_signature_method=”HMAC-SHA1″, oauth_timestamp=”1321927498″, oauth_nonce=”-8718158770338538733″, oauth_signature=”SoAGPsRU48uRE0B49p4UKTiEK9c%3D”
    11-22 02:04:58.880: INFO/System.out(6296): [SIGNPOST] Request URL: https://www.google.com/accounts/OAuthGetRequestToken?scope=https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2F
    11-22 02:05:00.420: DEBUG/dalvikvm(6296): GC_CONCURRENT freed 199K, 5% free 7050K/7367K, paused 2ms+1ms
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): Error during OAUth retrieve request token
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: Service provider responded in error: 400 (Bad Request)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:69)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at com.ecs.android.oauth.OAuthRequestTokenTask.doInBackground(OAuthRequestTokenTask.java:55)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at com.ecs.android.oauth.OAuthRequestTokenTask.doInBackground(OAuthRequestTokenTask.java:1)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at android.os.AsyncTask$2.call(AsyncTask.java:252)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:574)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at java.lang.Thread.run(Thread.java:1020)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): Caused by: oauth.signpost.exception.OAuthCommunicationException: Service provider responded in error: 400 (Bad Request)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:241)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
    11-22 02:05:00.800: ERROR/com.ecs.android.oauth.OAuthRequestTokenTask(6296): … 9 more
    11-22 02:05:05.070: DEBUG/dalvikvm(220): GC_EXPLICIT freed 1K, 31% free 17780K/25607K, paused 2ms+3ms

  23. vishal
    November 21st, 2011 at 12:11 | #27

    my bad.. time was not properly on device was causing this issue..

  24. kamal
    January 16th, 2012 at 12:54 | #28

    Hi,

    Great example here. But it is giving only some of the contacts from gmail. & i want the email ids of m friends. How can i get them.

    Thanks

  25. David
    February 27th, 2012 at 13:58 | #29

    Thank you so much for this. After a long process of working around a bug in the Android SDK installer, installing signpost, and then installing mosabua’s gitHub library, mvn install worked in this project’s root.

    How do I get this to compile in Eclipse?

    It gives me an error message in the manifest file that says, “Failed to load properties file for project ‘OAuthFlowApp’”

  26. David
    February 27th, 2012 at 20:49 | #30

    @David
    never mind! got it working. Thanks!

  27. jason
    March 27th, 2012 at 08:59 | #31

    will the access token expired?

  28. jason
    March 27th, 2012 at 09:39 | #32

    i manage to did this successfully. but my grant access is not showing in mobile page. any idea?

  29. Shah
    April 6th, 2012 at 20:10 | #33

    Hi.. It is a very well explained tutorial.. I have tired it but i’m getting error while retrieving my contacts.. “Error retrieving contacts” .. I can’t figure out where is the problem..

    Can someone please explain to me whats wrong in it ?

    Thanks in advance :)

  30. Shah
    April 6th, 2012 at 20:16 | #34

    This is the error list in LogCat .. Can anyone help me out in it :)

    04-07 00:56:18.263: E/com.google.apis.Main(9649): Error executing request
    04-07 00:56:18.263: E/com.google.apis.Main(9649): java.lang.ClassCastException: org.apache.http.message.BasicHttpResponse
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at com.google.apis.Main.doGet(Main.java:121)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at com.google.apis.Main.performApiCall(Main.java:65)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at com.google.apis.Main.onCreate(Main.java:56)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1072)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1836)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1893)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.ActivityThread.access$1500(ActivityThread.java:135)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1054)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.os.Looper.loop(Looper.java:150)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at android.app.ActivityThread.main(ActivityThread.java:4389)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at java.lang.reflect.Method.invokeNative(Native Method)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at java.lang.reflect.Method.invoke(Method.java:507)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
    04-07 00:56:18.263: E/com.google.apis.Main(9649): at dalvik.system.NativeStart.main(Native Method)

  31. Adrian
    May 8th, 2013 at 17:52 | #35

    Hi, after importing your program I have similiar problem like user above.

    Unable to instantiate activity ComponentInfo{com.ecs.android.oauth/com.ecs.android.oauth.OAuthFlowApp}: java.lang.ClassNotFoundException: com.ecs.android.oauth.OAuthFlowApp

    Anybody can help with it?

  1. November 19th, 2010 at 19:38 | #1
  2. January 3rd, 2011 at 09:28 | #2
  3. February 13th, 2011 at 16:36 | #3
  4. February 28th, 2011 at 20:34 | #4
  5. April 12th, 2011 at 17:24 | #5