This is not a complete guide to OAuth with Google, The Best reference I found was here:
http://code.google.com/apis/accounts/docs/OAuth_ref.html
I spent some time with OAuth, but I didn't find any working example with complete source code, only partial stuff here and there, so I wrote this simple example, that authenticate with Google Contacts Service, it can be easly adapted to authenticate with any Google Service.
This example use the signpost library, that makes life easy, so you don't have to deal with the HTTP level.
So Here is what I do:
- I separated the application to 2 activities, this is a must, and I learned it the hard way, because for some reason Android will not start the main activity on the BROWSABLE intent filter, so there is a secondary activity that listen to the browser callback and act on it.
- When clicking on the launchOauth button, the RequestTokenActivity is started.
launchOauth.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { startActivity(new Intent().setClass(v.getContext(), RequestTokenActivity.class)); } });
- RequestTokenActivity starts the OAuth dance, first initializing the consumer and provider, the calling the getRequestToken(), which starts the browser with the request token URL:
private void getRequestToken() { try { Log.d(C.TAG, "getRequestToken() called"); String url = provider.retrieveRequestToken(consumer, C.OAUTH_CALLBACK_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); this.startActivity(intent); } catch (Exception e) { Log.e(C.TAG, "Error retrieving request token", e); } }
- The browser lunched and redirected to Google accounts Authentication page, you can see that the application name "OAuth Example" is requesting permissions to access your contacts, the user should now click on the grant access button.
You can also notice that there is a warning on the page that states that google can't verify the application, this happens because we use anonymous consumer key and secret (in C.java)
public static final String CONSUMER_KEY = "anonymous"; public static final String CONSUMER_SECRET = "anonymous";
For production grade application get your consumer key and secret from Google.
- After the user clicked on the grant access, the browser callback is cached in the onNewIntent method (still in RequestTokenActivity),
public void onNewIntent(Intent intent) { super.onNewIntent(intent); prefs = PreferenceManager.getDefaultSharedPreferences(this); final Uri uri = intent.getData(); if (uri != null && uri.getScheme().equals(C.OAUTH_CALLBACK_SCHEME)) { Log.i(C.TAG, "Callback received : " + uri); Log.i(C.TAG, "Retrieving Access Token"); getAccessToken(uri); } }
in this callback URL we have the Verifier parameter, the getAccessToken method will first extract this Verifier, that grants a short time temporary access to get the access token, then will use it to call the provider retrieveAccessToken method:
final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER); ... provider.retrieveAccessToken(consumer, oauth_verifier);
Finally we have the access token! the concludes the OAuth dance, we now store the token and the token secret in the SharedPreferences for future use, and go back to the OAuthMain activity.
In the main activity we can now click on Get Contacts button, and see the list of contacts:
The code that is relevant to OAuth is in the makeSecuredReq (in OAuthMain.java),
Where is create the get contacts request and sign it using the consumer we create in the getConsumer Method (using the token and the secret we stored in the previous step).
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet request = new HttpGet(url); consumer.sign(request); HttpResponse response = httpclient.execute(request);
After we have the response we parse it using JSON (which is out of the scope of this tutorial, but is quite simple).
Thats it!
So Here is the Full Source Code of this example, hope you find it useful.
Gr8 tutorial, code works great!
ReplyDeleteTHX it is very clear ! :D AND HELPFULL can tel me how to i import Yahoo or hotmail contacts with it ? it is posibble to do such thing? or it is somthing else which is helpfuh :) THX
ReplyDeleteHi Red,
ReplyDeleteOAuth is open, but I'm not sure Yahoo or Hotmail implemented it on their side (google it), I know that Facebook and Twitter supports it (for login).
Hi John,
ReplyDeleteI have followed this tutorial but it is giving me a error:
"Could not find class 'oauth.signpost.commonshttp.CommonsHttpOAuthConsumer', referenced from method com.netcomps.oauth_example.RequestTokenActivity.onCreate".
Please help me.
rename the `lib` folder to `libs`
Deletei am also getting the same error
Delete"Could not find class 'oauth.signpost.commonshttp.CommonsHttpOAuthConsumer', referenced from method com.netcomps.oauth_example.RequestTokenActivity.onCreate".
tried lib to libs still getting the error ...
Right click the project & select properties, select Java Build Path, in that select Libraries tab & you will see two jar files with reference to old lib folder, so you have to remove those two jars & add new jar files i.e signpost-core & signpost-commonshttp from libs folder
DeleteHow do i get details of other than account names
ReplyDeletecould you suggest me for gmail login connectivity in android
ReplyDelete"Error retrieving request token" when execute.
ReplyDeleteI have downloaded your full source code and tried to execute but unfortunately got this error while clicking on button Do OAuth.
ReplyDeleteE/OAuthExample(3655): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: Service provider responded in error: 400 (Bad Request)
Check device date and time.
DeleteSame Error 12-22 java.lang.NoClassDefFoundError: oauth.signpost.commonshttp.CommonsHttpOAuthConsumer
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThere are few things you need to change to work around this error,
ReplyDelete1:
Go to Project -> Properties, and under your Java Build Path -> Order and Export tab make sure those JARs are checked.
2:
in manifest file,
change minSdkVersion to 8
3:
Go to Project -> Properties, and under Android -> set Project Build Target to Android 2.2
4:
You're done! Enjoy ;-)
Hey, It's working fine, but i am not getting all my contacts, can u give me the solution for this. Thanks
ReplyDeletehi this is not working for android ICS can u please help how to do in ICS making error the following
ReplyDelete04-12 18:13:30.011: E/OAuthExample(1370): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
04-12 18:13:30.011: E/OAuthExample(1370): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:69)
04-12 18:13:30.011: E/OAuthExample(1370): at com.ntc.gmailutilities.RequestTokenActivity.getRequestToken(RequestTokenActivity.java:54)
04-12 18:13:30.011: E/OAuthExample(1370): at com.ntc.gmailutilities.RequestTokenActivity.onCreate(RequestTokenActivity.java:34)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.Activity.performCreate(Activity.java:4465)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.ActivityThread.access$600(ActivityThread.java:123)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
04-12 18:13:30.011: E/OAuthExample(1370): at android.os.Handler.dispatchMessage(Handler.java:99)
04-12 18:13:30.011: E/OAuthExample(1370): at android.os.Looper.loop(Looper.java:137)
04-12 18:13:30.011: E/OAuthExample(1370): at android.app.ActivityThread.main(ActivityThread.java:4424)
04-12 18:13:30.011: E/OAuthExample(1370): at java.lang.reflect.Method.invokeNative(Native Method)
04-12 18:13:30.011: E/OAuthExample(1370): at java.lang.reflect.Method.invoke(Method.java:511)
04-12 18:13:30.011: E/OAuthExample(1370): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
04-12 18:13:30.011: E/OAuthExample(1370): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
04-12 18:13:30.011: E/OAuthExample(1370): at dalvik.system.NativeStart.main(Native Method)
04-12 18:13:30.011: E/OAuthExample(1370): Caused by: android.os.NetworkOnMainThreadException
04-12 18:13:30.011: E/OAuthExample(1370): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
04-12 18:13:30.011: E/OAuthExample(1370): at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
04-12 18:13:30.011: E/OAuthExample(1370): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
04-12 18:13:30.011: E/OAuthExample(1370): at java.net.InetAddress.getAllByName(InetAddress.java:220)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
04-12 18:13:30.011: E/OAuthExample(1370): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
04-12 18:13:30.011: E/OAuthExample(1370): at oauth.signpost.commonshttp.CommonsHttpOAuthProvider.sendRequest(CommonsHttpOAuthProvider.java:64)
04-12 18:13:30.011: E/OAuthExample(1370): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:177)
04-12 18:13:30.011: E/OAuthExample(1370): ... 17 more
not giving all contacts, solutions?
ReplyDeletechange your lib folder into libs ..... and app will be work its working for me
Deletechange your lib folder into libs ..... and app will be work its working for me
ReplyDeleteOnly 8 contacts will display.How can i get all contacts? Is there any solutions?
ReplyDeletehow to get email address
ReplyDeleteit's not working in minSdkVersion=9 or above.
ReplyDeleteall my contacts are not getting displayed and i need to display email address too.. wat should i add to the code.
ReplyDeleteplz help me out..