Preamble
Recently twitter turned off API 1.0 requiring applications to move to 1.1 and begin using OAuth for all API calls. For those of us who simply wanted to display a user’s timeline in our app, that means things just got a little more complicated.
There are essentially three ways to authenticate with Twitter
- Standard OAuth is what you’ll need to use if you want your users to be able to sign in with their own twitter credentials.
- Single user mode is great if you are the only person using your application. For instance if your washing machine tweets updates. It’s much simpler to setup than Standard OAuth, but all actions will be performed in the context of the single user you specify in the code. (more info here)
- Application Only is a little different in that instead of authenticating a user, you authenticate the application. Again, this type of authentication is a little easier to setup, but it comes with the limitation that you cannot perform any actions in the context of a user.
For my application I only needed to display the timelines from a handful of users. Since searching/reading tweets is public information I can use Application Only authentication. This process is documented already here, but this post will supplement some Android-specific code.
Prerequisites
The first thing you will need to do is sign into https://dev.twitter.com. Go to the “My Applications” section and create a new application for yourself. Twitter will assign you a Consumer Key and a Consumer Secret.
Getting Down to Business
We need to obtain a “bearer token” which will serve as the login credentials for our application. To obtain the bearer token we submit a specially formatted request to twitter. The request should look like this (without the line break on the Authorization line):
POST /oaut/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJnNmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzipgrant_type=client_credentials
We construct this request in Android as follows:
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams()); HttpPost httppost = new HttpPost("https://api.twitter.com/oaut/token"); final String APIKEY = "<Your Consumer Key>"; final String APISECRET = "<Your Consumer Secret>"; String apiString = APIKEY + ":" + APISECRET; String authorization = "Basic " + Base64.encodeToString(apiString.getBytes(), Base64.NO_WRAP); httppost.setHeader("Authorization", authorization); httppost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); httppost.setEntity(new StringEntity("grant_type=client_credentials")); InputStream inputStream = null; HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); inputStream = entity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "n"); }
The StringBuilder sb will now contain a JSON formatted response containing your bearer token. It will look something like this
{“token_type”:”bearer”,”access_token”:”AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”}
We will include the bearer token in every call we make to the API. It acts as our authentication. Before we jump into using the bearer token there are some things you should know about it.
- It uniquely identifies your application to twitter. Do not post it publicly.
- It can be revoked by twitter. If this happens, you will need to generate a new token using the process above.
- It can be revoked by you. You would want to do this if someone else obtained the token and was using it without your permission
So while theoretically you could hard code the bearer token into your app, it’s better to save it to your application’s database or as a preference. If the token is revoked, your application should run the code above to get a new token.
Making the Call
Calling the API with the bearer token is very similar to what we did before. We simply add the bearer token as a header in the HTTP request like this
GET /1.1/statuses/user_timeline.json?count=100&screen_name=twitterapi
HTTP/1.1 Host: api.twitter.com User-Agent: My Twitter App v1.0.23
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Accept-Encoding: gzip
Which is created by the following Android code. The variable url specifies the API you are attempting to access. For instance https://api.twitter.com/1.1/statuses/user_timeline.json?count=100&screen_name=twitterapi
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams()); HttpGet httpget = new HttpGet(url); httpget.setHeader("Authorization", "Bearer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); httpget.setHeader("Content-type", "application/json"); InputStream inputStream = null; HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); inputStream = entity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "n"); }
Once again, the StringBuilder sb will contain the JSON encoded response from the API.
Here is an example eclipse project. Simply provide your API Key and API Secret in MainActivity.java.
Would you please post a sourse code for this app it woud be much easier than to ask all the parts I didn’t get. Thank you!
I have attached an example project at the bottom of the post.
Not working for me. sb returns : {“errors”:[{“message”:”Bad Authentication data”,”code”:215}]}. Any ideas what Am I doing wrong?
That means twitter could not authenticate you because you did not supply the correct information.
1. Are you trying to use the tokens I provided in this post? They will not work, you need to provide your own.
You have sorted my life dude!!
I had been searching for this thing since 24 hrs..Thanks a ton!!!!!
InputStream inputStream = null;
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
from where did httpget come from..is that a typing error and shouldn’t it be httppost..
P.S. in the method that retrieves the bearer token.
Yes, fixed.
Thx a lot! Everything working now. Appreciate your post-)
Hello I put the API key and API secret of my application, run the application, and clicking on “get Bearer Token” gave me a string like “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAA….” but clicking on “Get Feed” returns nothing. Please help!
After reseting consumer key and consumer token, it’s finally working!
Thankkkkkkk yyyyyoooouuuuuuuuu!!!!!!!!!!
It really help me.
Thank you so much man!!!!
Thank you for the post. working perfetly
Any one know how to impliment this in ios
I realize that it has been months since someone has replied to this, but it was so helpful that I wanted to make so that I let you know. Thanks for spelling things out so well and supplying code. I’ve seen a number of posts that give details, but all of them leave out important information. Yours covered everything perfectly!
Thanks a lot,Thanks thanks
not able to access this :- https://api.twitter.com/1.1/statuses/home_timeline.json
Hi,
This is a superb post. Made my life easier. 😀
However, it failed to fetch the statuses if I change the screen_name from twitterapi to some other screen name. Anything that I’m missing?
Thanks,
Yellen