Android Twitter API 1.1 App
On June 11, 2013, Twitter turned off version 1.0 of their REST API. The API had been deprecated for quite sometime but still a lot of people were caught by surprise. All over the Internet a crap load of tutorials broke. Twitter was always a favorite for tutorial writers, since their servers were open and always had fresh data. Quite frankly, I was surprised how long Twitter let everyone and anyone use their servers. It was incredibly generous and must have been equally expensive.
Now the free ride isn't over. Twitter just wants to know who is using their servers. And they are using OAuth to do it. Now OAuth can be a bit tricky to work with, not overly painful, but tricky. It is also a bit of overkill if all you want to do is something as simple as grabbing a user's public timeline. Luckily, there is an easier alternative: Application-Only Authentication.
With application-only authentication, your app is able to make authenticated requests its own. It doesn't need a user's credentials. Now, it can't do everything. Since it is doesn't have a user context, it isn't able to do things like status updates. But it can do things like grabbing a user's timeline, which is what this tutorial will do.
Now the free ride isn't over. Twitter just wants to know who is using their servers. And they are using OAuth to do it. Now OAuth can be a bit tricky to work with, not overly painful, but tricky. It is also a bit of overkill if all you want to do is something as simple as grabbing a user's public timeline. Luckily, there is an easier alternative: Application-Only Authentication.
With application-only authentication, your app is able to make authenticated requests its own. It doesn't need a user's credentials. Now, it can't do everything. Since it is doesn't have a user context, it isn't able to do things like status updates. But it can do things like grabbing a user's timeline, which is what this tutorial will do.
YOU WILL NEED YOUR OWN CONSUMER KEY & SECRET!
I want to say that up front to hopefully stop people from complaining that the app doesn't work later. Getting a key and secret is easy and free so there is no good reason for not getting one. The app doesn't have a working key or secret. It will build, but it won't run until you replace the mock key and secret, with real ones.
Getting Your Own Consumer Key and Secret
- Simply go to https://dev.twitter.com
- Click the "Sign in" link in the upper right hand corner
- Enter your credentials and click "Log in"
- Hover over your avatar in the upper right hand corner
- Click the "My applications" link
- Click the "Create a new application" button
- Fill out the application details
- Accept the "Developer Rules of the Road"
- Complete the captcha
- Click the "Create your Twitter application" button
- On the "My applications" page, click on your application's name
- Your consumer key and secret will listed in the OAuth settings section
Keep your consumer key and secret secure. Don't do anything foolish with them, like publish them in a tutorial.
Android's Listview Adapter and AsyncTask
This app uses a quick and simply listview to render the tweets. It looks absolutely ugly, but this tutorial is about getting access to a user's timeline in API 1.1, not how to render pretty listview in Android. There are already a lot of tutorials out there on how to that.
We also make use of one of Android's cooler features, AsyncTasks. I hope that we all know by now, that we aren't suppose to do anything which takes a long time on the main UI thread, you know things like calling web services. The AsyncTask is probably the easiest way to avoid getting an ANR. And it is so dead simple to use.
The app uses a private class, DownloadTwitterTask which inherits from AsyncTask. Its job is to download the current batch of tweets on the user's timeline. The doInBackground method does all of the grunt work. It grabs the user's screen name, and calls the getTwitterStream method. This is what makes the AsyncTask class cool. You don't have to think about multi-tasking or other such complexity, just what is long running task you want to do, and do it.
Once your task is complete, return your object and AsyncTask will pass it on to the onPostExecute method which runs on the UI thread. This is the perfect time to update your UI. Now for us the string passed to the onPostExecute method is the user's timeline in JSON format, so we convert it to a Twitter object which we define as an array list of Tweets. We use Google's excellent Gson library to do that conversion and a few others. And finally we feed our tweets to the list adapter for rendering.
Getting Authenticated and a User's Timeline
We have rendered our tweets to our list view, but how did we get them? Once you have your key and secret, it is surprisingly simple to get to a user's timeline, just make a few HTTPS calls. In fact, Twitter lists out how to do it in three steps, well OK there are some sub-steps. The getTwitterStream method lists out all of the steps necessary to authenticate your app and then get some tweets.
Step 1: Encode consumer key and secret
First, we need to URL encode the consumer key and secret. Java has this function built-in, URLEncoder, be sure to pass your encoding. Then we concatenate the encoded strings with a semi-colon separating them and Base64 encode the whole thing. This is the one spot where I ran into some trouble. I wasn't sure what flag to pass. I initially tried, Base64.DEFAULT, which didn't work. Luckily there weren't that many options, when I tried Base64.NO_WRAP, it worked.
Step 2: Obtain a bearer token
In order to get the bearer token, you need to make a post request to the Twitter token URL. With the request, you need to pass a few header keys. If each of the keys isn't correct, your request will be rejected. Also the request body must only contain "grant_type=client_credentials", or your request will be rejected.
If everything went well, you will now have your bearer token. Be sure to check it as well. Its token should equal "bearer".
Step 3: Authenticate API requests with bearer token
With our token, we can now make API requests. Simply set the Authorization header equal to the string "Bearer " plus our access token. For both the Http Post and the Http Get, I use the same method getResponseBody to read the entire HTTP stream and return it as a string. Everywhere, if we encounter an exception, no attempt is made to recover, we usually return an empty string or a null.
Summary
Again, please don't forget to replace the dummy consumer key and secret with your own. The code will not work without it. The project is in IntelliJ IDEA format. I just can't bring myself to use Eclipse. If you use Eclipse, simply copy the files into your project. Please feel free to use the code however you'd like.
Resources