Important note : As an update to this article, I’ve prepared a new post entitled Improved Twitter OAuth for Android focussing on a more simple Oauth / Android experience, and using the Google APIs Client Library for Java. The goal of this article is to get twitter integration up & running from your Android app in 30 minutes. The guide will show you how to
This guide is accompanied by a sample application that’s available in Github in the AndroidTwitterSample repository. To import this project in Eclipse, I suggest using the EGit plugin that can be installed via the Main P2 Repository located at http://download.eclipse.org/egit/updates. |
Image may be NSFW. Clik here to view. ![]() |
Before running this project, make sure you change the com.ecs.android.sample.twitter.Constants file to include your consumer key and consumer secret. (see subsequent section).
Once you have sample application up & running, you can copy the relevant classes into your projects to have Twitter up & running.
Twitter uses the OAuth protocol to authorize your android application to send tweets on behalf of the end-user. The end-user will need to authenticate against Twitter (meaning that your application will not capture the twitter username / password). Once the user has authorized access, you’ll be able to send tweets on behalf of the user. We’ll use signpost library to handle the OAuth communication, and the Twitter4J library to handle the Twitter specific interactions (sending tweets).
Setting up the Twitter account and application.
We’ll start by setting up a test-account on Twitter that we’ll use in our Android application. Goto the Twitter signup page and create an account. You’ll receive an email from Twitter to confirm your account. You can skip the friends import as it will only be used for testing purposes.
Image may be NSFW.
Clik here to view.
Now that we have the Twitter account setup, we need to define an application. Go to the Twitter Application Registration page, and register an application. The application that your register here is required to perform Twitter interaction from your Android application. The Twitter application will have a consumer key and consumer secret associated with it that we’ll use in our Android application.
Fill in the required fields like you can see in the screenshot below :
Image may be NSFW.
Clik here to view.
Once the application is registered, you’ll receive the following information associated with your application :
************************ (masked)
Consumer secret
************************ (masked)
Request token URL
https://api.twitter.com/oauth/request_token
Access token URL
https://api.twitter.com/oauth/access_token
Authorize URL
https://api.twitter.com/oauth/authorize
Registered OAuth Callback URL
http://someurl.com
This is all the information we need to start integrating Twitter in our Android application.
Note : The callback URL specified here is just a required field that we need to fill in, but is not used in our application. Instead, we define our own callback URL that we’ll pass on when authenticating the user
The sample application
The sample application is available in Github in the AndroidTwitterSample repository. Before running this project, make sure you change the com.ecs.android.sample.twitter.Constants file to include your consumer key and consumer secret. The application provides you with an end-to-end example on how to authenticate against Twitter and send tweets on behalf or the authenticated user.
The sample project has a dependency towards the following libraries :
- signpost-commonshttp4-1.2.1.1.jar
- signpost-core-1.2.1.1.jar
- httpclient-4.0.1.jar
- twitter4j-core-2.1.11
Dev note : You’ll need to include these libraries into your own project if you want to enable the Twitter integration.
The sample application contains 1 main activity with
- a status message, indicating if you’re logged into Twitter.
- a Tweet button, used to send a Tweet. When not authenticated, the application will redirect you to the Twitter loging page.
- a Clear Credentials button, removing all saved credentials, forcing you to login next time you want to send a Tweet.
Image may be NSFW.
Clik here to view.
The Constants file
The Android project contains a Constants file containing the following information we received from Twitter when we setup our application.
public class Constants { public static final String CONSUMER_KEY = "<FILL IN YOUR CONSUMER KEY FROM TWITTER HERE>"; public static final String CONSUMER_SECRET= "<FILL IN YOUR CONSUMER SECRET FROM TWITTER HERE>"; public static final String REQUEST_URL = "http://api.twitter.com/oauth/request_token"; public static final String ACCESS_URL = "http://api.twitter.com/oauth/access_token"; public static final String AUTHORIZE_URL = "http://api.twitter.com/oauth/authorize"; final public static String CALLBACK_SCHEME = "x-latify-oauth-twitter"; final public static String CALLBACK_URL = CALLBACK_SCHEME + "://callback"; }
Dev note : If you want to integrate Twitter in your own app, I suggest making similar Constants available throughout your application.
What we have defined in the Constants class :
CONSUMER_KEY | A key used when communicating with Twitter. This unique key is tied to the application we defined at Twitter that will be used by our Android app. The name of the application will be shown to the user when he authenticates against Twitter. This key is provided to you after registering an application at Twitter. |
CONSUMER_SECRET | The secret associated with the unique key. Think if this as a password where the key is a username. This key is provided to you after registering an application at Twitter. |
REQUEST_URL | URL needed to retrieve a request token. Part of the OAuth spec. This URL is provided to you after registering an application at Twitter. |
AUTHORIZE_URL | URL needed to authorize the application access to Twitter. Part of the OAuth spec. This URL is provided to you after registering an application at Twitter. |
ACCESS_URL | URL needed to retrieve an access token. Part of the OAuth spec. This URL is provided to you after registering an application at Twitter. |
CALLBACK SCHEME | A unique identifier within our Android app that we’ll use as a callback to retrieve the access token. This scheme can be freely choosen, but should be fairly unique to your application. We’ll use x-sample-oauth-twitter here. |
CALLBACK_URL | The redirect URL that Twitter will use after the user has authorized the request. When Twitter redirects to this URL, our Android application will take over to retireve the access token embedded in this URL. |
The tweet button
The code behind the Tweet button is implemented like this :
tweet.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (TwitterUtils.isAuthenticated(prefs)) { sendTweet(); } else { Intent i = new Intent(getApplicationContext(), PrepareRequestTokenActivity.class); i.putExtra("tweet_msg",getTweetMsg()); startActivity(i); } } });
From a user experience, we opted to not have a seperate login button, but just have a single Tweet button, and encapsulate the authentication logic inside the Tweet login.
Basically, it performs a check to see if the user has already authenticated to Twitter.
- If not, he’ll be redirected to the twitter login page by popping a browser. Once the user has authenticated, he’ll authorize the Android application to send tweets on the users behalf and the tweet will be sent (notice how we pass the tweet msg to the Intent when starting the PrepareRequestTokenActivity activity).
- If the user was already authenticated before, the tweet will be sent immediately.
Authenticating the user
We’ll start with the first case, where the user hasn’t authenticated to Twitter yet. This is the most complex part, as it involves implementing the OAuth flow to finally retrieve an access token.
This complete OAuth implementation is done in the OAuthRequestTokenTask and the PrepareRequestTokenActivity classes.
Before the user can authorize our application to send Tweets on his behalf, we’ll first need to redirect the user to the Twitter login page. This is done through the PrepareRequestTokenActivity. This will kick in the OAuth interactions required for your application to send tweets on behalf of the logged in user.
Dev note : I suggest copying these 2 classes into your own project, as they have been setup in a generic way.
The following table shows you in detail what each class does :
PrepareRequestTokenActivity | Sets up the OAuth consumer and producer objects (Signpost library) and starts the asynchronous OAuthRequestTokenTask. Also handles the callback when the authentication is done to retrieve the access token. |
OAuthRequestTokenTask | Responsible for retrieving the request token, and popping a browser so that the user can authorizing our application to send Tweets on his behalf. |
RetrieveAccessTokenTask | Inner class in PrepareRequestTokenActivity. Triggered from the PrepareRequestTokenActivity onNewIntent method. After the user has logged in and authorized access, this task will retrieve the access token and store it in the shared preferences. |
The PrepareRequestTokenActivity activity sets up our OAuth consumer and provider (using the Signpost library), and starts an Asynchronous task called OAuthRequestTokenTask.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { this.consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET); this.provider = new CommonsHttpOAuthProvider(Constants.REQUEST_URL,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(); }
This asynchronous task just starts an Intent that launches a browser to authenticate the user against Twitter. At this point, our Android application gives control to Twitter. The user enters his username/password, and Twitter will do the authentication. Notice how we also specify a callback URL. Twitter will redirect to this callback URL after the user has properly authenticated against twitter. In our case, the callback URL is x-oauthflow-twitter://callback. This callback is required to give back the control to our Android application.
@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; }
The twitter login page
Image may be NSFW.
Clik here to view.
In our AndroidManifest.xml, The PrepareRequestTokenActivity, responsible for popping the browser has an intent filter defined with a scheme and host that corresponds to our 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-twitter" android:host="callback" /> </intent-filter> </activity>
Dev note : You’ll need to include this activity into your own project if you want to enable the Twitter integration.
Due to the fact that we have the intent filter defined we’ll be able to intercept the callback that Twitters sends. So after the user authenticated, Twitter sends a redirect to our callback URL, causing our onNewIntent method to kick in. At this point, we can continue with the OAuth flow and retrieve the access token using the RetrieveAccessTokenTask.
@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 RetrieveAccessTokenTask is responsible for capuring the access token, required to do communication with Twitter.
It basically extracts the access token from the callback URL, passed on to it from the previous code snippet. We then store the access token and secret in our shared preferences, so that the user doesn’t need to login to Twitter again, not even after restarting the application.
@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,AndroidTwitterSample.class)); executeAfterAccessTokenRetrieval(); Log.i(TAG, "OAuth - Access Token Retrieved"); } catch (Exception e) { Log.e(TAG, "OAuth - Access Token Retrieval Error", e); } return null; }
Notice the executeAfterAccessTokenRetrieval method, that will be executed after having retrieved the access token. We’ll use this hook to actually send the message now.
It basically extracts the tweet message from the Intent that was passed along in the beginning of the OAuth flow (when clicking the Tweet button).
private void executeAfterAccessTokenRetrieval() { String msg = getIntent().getExtras().getString("tweet_msg"); try { TwitterUtils.sendTweet(prefs, msg); } catch (Exception e) { Log.e(TAG, "OAuth - Error sending to Twitter", e); } }
Sending the Tweet
Sending the actual Tweet is via a background thread like this :
public void sendTweet() { Thread t = new Thread() { public void run() { try { TwitterUtils.sendTweet(prefs,getTweetMsg()); mTwitterHandler.post(mUpdateTwitterNotification); } catch (Exception ex) { ex.printStackTrace(); } } }; t.start(); }
In order to provide feedback to the user (Toast message), we perform a post to a handler defined in our main Activity.
private final Handler mTwitterHandler = new Handler(); final Runnable mUpdateTwitterNotification = new Runnable() { public void run() { Toast.makeText(getBaseContext(), "Tweet sent !", Toast.LENGTH_LONG).show(); } };
The actual sending of the Tweet is done through the Twitter4J library, where we retrieve the access token and secret. We set the consumer key, consumer secret and access token on our Twitter object, and call the updateStatus method to send our Tweet.
public static void sendTweet(SharedPreferences prefs,String msg) throws Exception { String token = prefs.getString(OAuth.OAUTH_TOKEN, ""); String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, ""); AccessToken a = new AccessToken(token,secret); Twitter twitter = new TwitterFactory().getInstance(); twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET); twitter.setOAuthAccessToken(a); twitter.updateStatus(msg); }
After making this call, your Tweet will be visible on your Twitter page :
Image may be NSFW.
Clik here to view.