Android Twitter Feed Reader

This Android tutorial is to demonstrate an application that will connect to the Twitter and read the tweets and display it. We will use the Twitter 1.1 API to access the tweets by authenticating via OAuth. We will be using the gson-2.2.4.jar for parsing the Json response. Apart from the gson API we will not be using any other third party APIs, just plain Java will do the job.

This Android example application is simple and powerful. We Android fans can build our own Twitter client using this as a base. With very little modifications this can be used as a generic Json feed reader or this can be even customized as a web application or a desktop client. I have layered the files for easy separation based on its responsibilities.

Twitter-Feed-Reader

Download Android Twitter Feed Reader Application Project Source

Twitter Feed Reader App Demo


Twitter Feed Reader Application

Following are the key subsections in building this Twitter feed reader Android application.

  • Twitter OAuth Authentication
  • Android Async Task
  • Twitter Json Reader

Twitter OAuth Authentication

We will use the Twitter OAuth2 API to authenticate with the Twitter backend. From Twitter 1.1 API we need to authenticate to read the tweets. We will follow the standard OAuth communication protocol for authentication. Previously we did a web application to authenticate with Facebook using OAuth. It gives more detail about the OAuth steps to be performed for authentication.

TwitterAPI.java

package com.javapapers.social.twitter;

import android.util.Base64;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.javapapers.java.io.HttpUtil;

import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;

public class TwitterAPI {

    private String twitterApiKey;
    private String twitterAPISecret;
    final static String TWITTER_TOKEN_URL = "https://api.twitter.com/oauth2/token";
    final static String TWITTER_STREAM_URL = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=";

    public TwitterAPI(String twitterAPIKey, String twitterApiSecret){
        this.twitterApiKey = twitterAPIKey;
        this.twitterAPISecret = twitterApiSecret;
    }

    public ArrayList<TwitterTweet> getTwitterTweets(String screenName) {
        ArrayList<TwitterTweet> twitterTweetArrayList = null;
        try {
            String twitterUrlApiKey = URLEncoder.encode(twitterApiKey, "UTF-8");
            String twitterUrlApiSecret = URLEncoder.encode(twitterAPISecret, "UTF-8");
            String twitterKeySecret = twitterUrlApiKey + ":" + twitterUrlApiSecret;
            String twitterKeyBase64 = Base64.encodeToString(twitterKeySecret.getBytes(), Base64.NO_WRAP);
            TwitterAuthToken twitterAuthToken = getTwitterAuthToken(twitterKeyBase64);
            twitterTweetArrayList = getTwitterTweets(screenName, twitterAuthToken);
        } catch (UnsupportedEncodingException ex) {
        } catch (IllegalStateException ex1) {
        }
        return twitterTweetArrayList;
    }

    public ArrayList<TwitterTweet> getTwitterTweets(String screenName,
                                                     TwitterAuthToken twitterAuthToken) {
        ArrayList<TwitterTweet> twitterTweetArrayList = null;
        if (twitterAuthToken != null && twitterAuthToken.token_type.equals("bearer")) {
            HttpGet httpGet = new HttpGet(TWITTER_STREAM_URL + screenName);
            httpGet.setHeader("Authorization", "Bearer " + twitterAuthToken.access_token);
            httpGet.setHeader("Content-Type", "application/json");
            HttpUtil httpUtil = new HttpUtil();
            String twitterTweets = httpUtil.getHttpResponse(httpGet);
            twitterTweetArrayList = convertJsonToTwitterTweet(twitterTweets);
        }
        return twitterTweetArrayList;
    }

    public TwitterAuthToken getTwitterAuthToken(String twitterKeyBase64) throws UnsupportedEncodingException {
        HttpPost httpPost = new HttpPost(TWITTER_TOKEN_URL);
        httpPost.setHeader("Authorization", "Basic " + twitterKeyBase64);
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        httpPost.setEntity(new StringEntity("grant_type=client_credentials"));
        HttpUtil httpUtil = new HttpUtil();
        String twitterJsonResponse = httpUtil.getHttpResponse(httpPost);
        return convertJsonToTwitterAuthToken(twitterJsonResponse);
    }

    private TwitterAuthToken convertJsonToTwitterAuthToken(String jsonAuth) {
        TwitterAuthToken twitterAuthToken = null;
        if (jsonAuth != null && jsonAuth.length() > 0) {
            try {
                Gson gson = new Gson();
                twitterAuthToken = gson.fromJson(jsonAuth, TwitterAuthToken.class);
            } catch (IllegalStateException ex) { }
        }
        return twitterAuthToken;
    }

    private ArrayList<TwitterTweet> convertJsonToTwitterTweet(String twitterTweets) {
        ArrayList<TwitterTweet> twitterTweetArrayList = null;
        if (twitterTweets != null && twitterTweets.length() > 0) {
            try {
                Gson gson = new Gson();
                twitterTweetArrayList =
                        gson.fromJson(twitterTweets, new TypeToken<ArrayList<TwitterTweet>>(){}.getType());
            } catch (IllegalStateException e) {
            }
        }
        return twitterTweetArrayList;
    }
    private class TwitterAuthToken {
        String token_type;
        String access_token;
    }
}

Twitter Developer Application

Pre-requisite to access the Twitter API is a that we need

  1. Twitter API Key
  2. Twitter API Secret

We need to create an application from the Twitter Developer dashboard as below:

Create-Twitter-Application

After creating a Twitter application, we can get the Twitter API keys as below:

Twitter-API-Keys

We need these API Key and API secret to access the Twitter tweets. Keep those secret and they are like password.

Android Twitter Async Task

We need to make the network calls in Activity independent way using an AsyncTask. All it does is accesses our own custom Twitter API to authenticate and read the Tweets. Once the Twitter tweets are read successfully then it forwards the content to the Main Activity.

TwitterAsyncTask.java

package com.javapapers.android.twitterfeedreader.app;

import android.app.ListActivity;
import android.text.method.LinkMovementMethod;
import android.widget.ArrayAdapter;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.TextView;

import com.javapapers.social.twitter.TwitterAPI;
import com.javapapers.social.twitter.TwitterTweet;

import java.util.ArrayList;

public class TwitterAsyncTask extends AsyncTask<Object, Void, ArrayList<TwitterTweet>> {
    ListActivity callerActivity;

    final static String TWITTER_API_KEY = "UjqqnYRTxH6jOozcPYlRJKS";
    final static String TWITTER_API_SECRET = "rWjmk35PyGKaTEWzSZj0AN73d5dflOpwlBRfYozxw341R";

    @Override
    protected ArrayList<TwitterTweet> doInBackground(Object... params) {
        ArrayList<TwitterTweet> twitterTweets = null;
        callerActivity = (ListActivity) params[1];
        if (params.length > 0) {
            TwitterAPI twitterAPI = new TwitterAPI(TWITTER_API_KEY,TWITTER_API_SECRET);
            twitterTweets = twitterAPI.getTwitterTweets(params[0].toString());
        }
        return twitterTweets;
    }

    @Override
    protected void onPostExecute(ArrayList<TwitterTweet> twitterTweets) {
        ArrayAdapter<TwitterTweet> adapter =
                new ArrayAdapter<TwitterTweet>(callerActivity, R.layout.twitter_tweets_list,
                        R.id.listTextView, twitterTweets);
        callerActivity.setListAdapter(adapter);
        ListView lv = callerActivity.getListView();
        lv.setDividerHeight(0);
        //lv.setDivider(this.getResources().getDrawable(android.R.color.transparent));
        lv.setBackgroundColor(callerActivity.getResources().getColor(R.color.Twitter_blue));
    }
}

Android Activity with Cards List View

Sometime back we gone through a tutorial which explains to build an Android custom ListView using cards view. This completely explains how to build the UI for this application.

MainActivity.java

package com.javapapers.android.twitterfeedreader.app;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;

import com.javapapers.android.util.AndroidNetworkUtility;

public class MainActivity extends ListActivity {

    final static String twitterScreenName = "BBCNews";
    final static String TAG = "MainActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidNetworkUtility androidNetworkUtility = new AndroidNetworkUtility();
        if (androidNetworkUtility.isConnected(this)) {
            new TwitterAsyncTask().execute(twitterScreenName,this);
        } else {
            Log.v(TAG, "Network not Available!");
        }
    }
}

Following are the util classes used to peform other supportive tasks.

AndroidNetworkUtility.java

package com.javapapers.android.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class AndroidNetworkUtility {

    public boolean isConnected(Context ctx){
        boolean flag = false;
        ConnectivityManager connectivityManager =
                (ConnectivityManager) ctx.getSystemService(ctx.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            flag = true;
        }
        return flag;
    }
}

HttpUtil.java

package com.javapapers.java.io;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class HttpUtil {

    public String getHttpResponse(HttpRequestBase request) {
        String result = null;
        try {

            DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
            HttpResponse httpResponse = httpClient.execute(request);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            String reason = httpResponse.getStatusLine().getReasonPhrase();
            StringBuilder sb = new StringBuilder();
            if (statusCode == 200) {
                HttpEntity entity = httpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader bReader = new BufferedReader(
                        new InputStreamReader(inputStream, "UTF-8"), 8);
                String line = null;
                while ((line = bReader.readLine()) != null) {
                    sb.append(line);
                }
            } else {
                sb.append(reason);
            }
            result = sb.toString();
        } catch (UnsupportedEncodingException ex) {
        } catch (ClientProtocolException ex1) {
        } catch (IOException ex2) {
        }
        return result;
    }
}

Following are the POJOs that are data transfer objects

TwitterTweet.java

package com.javapapers.social.twitter;

import com.google.gson.annotations.SerializedName;

public class TwitterTweet {

	@SerializedName("created_at")
	private String createdAt;

	@SerializedName("id")
	private String id;

	@SerializedName("text")
	private String text;

	@SerializedName("in_reply_to_status_id")
	private String inReplyToStatusId;

	@SerializedName("in_reply_to_user_id")
	private String inReplyToUserId;

	@SerializedName("in_reply_to_screen_name")
	private String inReplyToScreenName;

	@SerializedName("user")
	private TwitterUser twitterUser;

	public String getCreatedAt() {
		return createdAt;
	}
	
	public String getId() {
		return id;
	}

	public String getInReplyToScreenName() {
		return inReplyToScreenName;
	}

	public String getInReplyToStatusId() {
		return inReplyToStatusId;
	}

	public String getInReplyToUserId() {
		return inReplyToUserId;
	}

	public String getText() {
		return text;
	}

	public void setCreatedAt(String createdAt) {
		this.createdAt = createdAt;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setInReplyToScreenName(String inReplyToScreenName) {
		this.inReplyToScreenName = inReplyToScreenName;
	}
	
	public void setInReplyToStatusId(String inReplyToStatusId) {
		this.inReplyToStatusId = inReplyToStatusId;
	}
	
	public void setInReplyToUserId(String inReplyToUserId) {
		this.inReplyToUserId = inReplyToUserId;
	}
	
	public void setText(String text) {
		this.text = text;
	}

	public void setTwitterUser(TwitterUser twitterUser) {
		this.twitterUser = twitterUser;
	}

	public TwitterUser getTwitterUser() {
		return twitterUser;
	}

	@Override
	public String  toString(){
		return getText();
	}
}

TwitterUser

package com.javapapers.social.twitter;

import com.google.gson.annotations.SerializedName;

public class TwitterUser {

	@SerializedName("screen_name")
	private String screenName;
	
	@SerializedName("name")
	private String name;
	
	@SerializedName("profile_image_url")
	private String profileImageUrl;

	public String getProfileImageUrl() {
		return profileImageUrl;
	}

	public String getScreenName() {
		return screenName;
	}

	public void setProfileImageUrl(String profileImageUrl) {
		this.profileImageUrl = profileImageUrl;
	}

	public void setScreenName(String screenName) {
		this.screenName = screenName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Download the project application source to get the complete files.

Download Android Twitter Feed Reader Application Project Source

This Android tutorial was added on 18/08/2014.

Comments on "Android Twitter Feed Reader" Tutorial:

  1. gaurav says:

    thanks for sharing the code. Its working fine.
    But one problem I am facing that I am able to retrieve 20 tweets only.
    Is it possible to retrieve all the tweets?

  2. Lays says:

    I get an Error:
    Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1
    at com.google.gson.Gson.fromJson(Gson.java:815)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at de.XX.XX.XX.TwitterAPI.convertJsonToTwitterTweet(TwitterAPI.java:83)
    at de.XX.XX.XX.TwitterAPI.getTwitterTweets(TwitterAPI.java:52)
    at de.XX.XX.XX.TwitterAPI.getTwitterTweets(TwitterAPI.java:36)
    at de.XX.XX.XX.TwitterAsyncTask.doInBackground(TwitterAsyncTask.java:22)
    at de.XX.XX.XX.TwitterAsyncTask.doInBackground(TwitterAsyncTask.java:10)

Your Comment

↑ Go to top