Using Scribe with Android
Filed Under (android, java, programming) by Nathan Schwermann on 13-04-2011
Tagged Under : android, java, OAuth, programming, sso, twitter
Recently I have been working on signing in with social networks with Android applications. I found a great article using Twitter4J to log in with twitter but I would like to expand on that article and rather than relying on an intent-filter and the default android browser I am adding a WebViewClient to handle the callback url.
Using an intent-filter and the default browser has two problems. One, depending on what browser the user has set as their default browser there is a chance that the browser won’t initiate an ACTION_VIEW intent but rather just attempt to load the callback url. Secondly, when your app goes into the background and the default browser opens there is a chance that onDestory would be called on the Activity and then onNewIntent wouldn’t be called. Although that could be handled in a number of different ways. Finally, instead of using Twitter4J I opted for Scribe instead. Mainly because it is designed to work with and already has support for many other social networks besides Twitter.
It just about 80 lines of code we can have the user sign in and verify their account. Of course we have no error handling yet, and the next step would be to move this to the new Fragment API to so you can easily attach it to any Activity to sign in with Twitter.
package net.schwiz.oauth;
import org.json.JSONException;
import org.json.JSONObject;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TwitterApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
/**
*Demonstrates how to use the scribe library to login with twitter.
*
*/
public class Main extends Activity {
final static String APIKEY = null;
final static String APISECRET = null;
final static String CALLBACK = "oauth://twitter";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView)findViewById(R.id.textview);
final WebView webview = (WebView) findViewById(R.id.webview);
if(APIKEY == null || APISECRET == null){
textView.setText("You must enter your own APIKEY and SECRET to use this demo. dev.twitter.com");
webview.setVisibility(View.GONE);
return;
}
//set up service and get request token as seen on scribe website
//https://github.com/fernandezpablo85/scribe-java/wiki/Getting-Started
final OAuthService s = new ServiceBuilder()
.provider(TwitterApi.class)
.apiKey(APIKEY)
.apiSecret(APISECRET)
.callback(CALLBACK)
.build();
final Token requestToken = s.getRequestToken();
final String authURL = s.getAuthorizationUrl(requestToken);
//attach WebViewClient to intercept the callback url
webview.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//check for our custom callback protocol otherwise use default behavior
if(url.startsWith("oauth")){
//authorization complete hide webview for now.
webview.setVisibility(View.GONE);
Uri uri = Uri.parse(url);
String verifier = uri.getQueryParameter("oauth_verifier");
Verifier v = new Verifier(verifier);
//save this token for practical use.
Token accessToken = s.getAccessToken(requestToken, v);
//host twitter detected from callback oauth://twitter
if(uri.getHost().equals("twitter")){
OAuthRequest req = new OAuthRequest(Verb.GET, "http://api.twitter.com/1/account/verify_credentials.json");
s.signRequest(accessToken, req);
Response response = req.send();
try {
JSONObject json = new JSONObject(response.getBody());
textView.setText(json.toString(3));
} catch (JSONException e) {
e.printStackTrace();
}
}
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
});
//send user to authorization page
webview.loadUrl(authURL);
}
}
Don’t forget to add the internet permission to your manifest! Also please note you will get a forceclose if you don’t add your own twitter API key. If you would like the full source code you can find it here.

Thanks. This is what I have been trying to convert my existing solution to, since a very long time.
But I haven't used Scribe. is it better than twitter4J?
It depends on what you are wanting to do. Scribe supports basic authentication for a lot of websites but Twitter4J has support for a ton of the twitter API calls. If you are just wanting to use twitter or other sites as authenticators (ie login with facebook, login with twitter, etc) then Scribe would be the way to go. If you are wanting to make a full fledged twitter app then there will be a lot of extra work supporting the additional API calls for twitter using Scribe.
I am trying to use this and having problems with the callback URL. On my twitter account I have it set to client (no callback URL). Should this be browser?
And can you breakdown your callback URL? Im guessing oauth is from the package name. But where did the twitter part come from? Doesnt seem to have anything to do with your activity. I need twitter to return to my activity called TwitterActivity (one of many activities in my application).
Btw, the error related to the callback URL is Web page not available
In my account settings I have it set to browser, I put a arbitrary URL on the website (schwiz.net) but I am not sure it is required that you put a URL in as it isn't the same callback URL I use in the app.
As you saw I used the callback url oauth://twitter
I chose oauth:// as my custom protocol here also as arbitrary protocol just so I would have a way to recognize the callback url in my WebClient (line 57 above).
I chose twitter as the host so I could reuse my WebViewClient for other social networks. On line 69 I check that the host is twitter and then I verify the credentials.
I hope that this clarifies things for you!
That was it. I cant believe thats all it was. I was trying to use something similar to my application name. And since I didnt change the .equals() to check that change. It was giving me the error mentioned below. Now I have access to the keys to post a status update on the twitter account that is logged onto, right? I havent tried yet, as Im just posting because Im happy that it works now.
Thanks a lot for your help and the demo.
I have executed the the sample. Login page is opening. Now I need to post a message to twitter.what is the procedure to achieve this using this Scribe Library.
Yes Keith we intercept the callback in this example and never load it in the webview. We use the callback url to identify what social network we have just authenticated and then parse out the token that is returned.
sounds like a good example for another post I will try to get to it soon.
This is really strange ! Scribe isn't accepting my APIKEY/SECRET . I've copied and pasted it directly from the site . Any clue why this is ???
E/AndroidRuntime( 2527): FATAL EXCEPTION: main
E/AndroidRuntime( 2527): java.lang.RuntimeException: Unable to start activity Co
mponentInfo{net.schwiz.oauth/net.schwiz.oauth.Main}: org.scribe.exceptions.OAuth
Exception: Response body is incorrect. Can't extract a token from this: 'Failed
to validate oauth signature and token'
E/AndroidRuntime( 2527): at android.app.ActivityThread.performLaunchActiv
ity(ActivityThread.java:2663)
E/AndroidRuntime( 2527): at android.app.ActivityThread.handleLaunchActivi
ty(ActivityThread.java:2679)
E/AndroidRuntime( 2527): at android.app.ActivityThread.access$2300(Activi
tyThread.java:125)
E/AndroidRuntime( 2527): at android.app.ActivityThread$H.handleMessage(Ac
tivityThread.java:2033)
E/AndroidRuntime( 2527): at android.os.Handler.dispatchMessage(Handler.ja
va:99)
E/AndroidRuntime( 2527): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 2527): at android.app.ActivityThread.main(ActivityThrea
d.java:4627)
E/AndroidRuntime( 2527): at java.lang.reflect.Method.invokeNative(Native
Method)
I copied the code from your blog because your link isn't working anymore. I built a main.xml file with a TextView and a Webview but when I run it with my key, I got a FATAL EXCEPTION main. I already have the Scribe library installed for something else.
It seems that something fails when it wants to start the activity. Any idea why it doesn't work? Do you still have the full source files?
Thanks,
can i use twitter4j after i have successfully autorized / logged in using scribe?
how can i retweet or tweet using scribe?
I was wondering, what do you mean about making this code use fragment api?
Do you want to have the browser be on a small section of your main activity?
Could you elaborate? Thank you!
And thanks for the guide. It was really helpful
I am referring to the Fragment API in the support library and Android 3.0+ It allows you to drop a section of code in any Activity making it a little more portable. http://developer.android.com/reference/android/su…
I'm not sure on that, I'll look into it I'm going to have some downtime this summer and Its important that this works on 4.0!
Yes I think you could use the authkey with whatever library you like once you retrieve it.
I'm not sure a few people have been getting the error. I will look into it over the next few weeks.
Hello,
Thanks for posting this! I'm trying to run it as an AsyncTask because my target SDK is 14 (HTTP requests can't be ran on the main thread). For some reason I keep getting a fatal exception when I do anything with the webview (starting at line 48).
I've tried a few different things with no luck. Any ideas???
Thanks!
[...] Schwiz Logcat » Blog Archive » Using Scribe with AndroidApr 13, 2011 … Filed Under (android, java, programming) by Nathan Schwermann on 13-04- … Finally, instead of using Twitter4J I opted for Scribe instead. No Comments 2066 [...]
Yaaa I have exactly the same error!
Did anybody find a solution?
Sorry for the late reply, I just went over this code and double checked its working on latest version of android. You need to make sure you supplied your own working APIKEY and APISECRET. That seems to be your trouble.
Works like a charm, thank you! Finally an easy to implement OAuth for Android!
Hi there, I wrote an android library that wraps up scribe but ease the asynchronous interaction for http requests and authentication. Hoping that it may help somebody, the link is https://github.com/fedepaol/PostmanLib–Rings-Twi…