Introduction
Twitter is very popular media for content sharing and social networking. Here in this article, we explore how to display Twitter statuses, known as tweet, in Android application.
Twitter API
Twitter provide API which developer can use to build application around Twitter functionalities. It has good documentation and many code samples to try. In this article, we only use Twitter statuses functionality. For complete list of Twitter API functionalities, please refer to Twitter API documentation.
Every tweets from a user is assumed public unless user makes it private. That means everyone can view your tweets if they know your user account. However, your application is guest to Twitter API environment so it should play nice with Twitter environment. For example, your application is only allowed to make 150 REST request per hour and 1000 statuses update for a day. For complete terms and condition please refer to Twitter documentation.
Twitter API uses REST (Representational State Transfer) so any request is sent as HTTP request such GET or POST just like browsing web pages.
Get user statuses update
Tweets is presented by Twitter API as JSON or XML. For example to get public statuses of username zpjuhara (my personal Twitter account) in JSON format:
https://api.twitter.com/1/statuses/user_timeline/zpjuhara.json
Update (9 Jul 2015): Twitter REST API version 1.0 is no longer active, so URL above will not work anymore and you will get JSON response like this:
{"errors":[{"message":"The Twitter REST API v1 is no longer active. Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.","code":64}]}
You need to migrate to version 1.1 by replacing
1 in URL above with
1.1. Since API v1.1, you need to use
OAuth to authenticate your request.
HTTP libraries in Android
Android provides two flavour of HTTP libraries, HTTPClient (org.apache.http.client.HttpClient) and HttpURLConnection (java.net.HttpURLConnection) or HttpsURLConnection (javax.net.ssl.HttpsURLConnection) for HTTPS protocol.
The first is still supported. However, Android SDK developer stated that they put their development efforts on HttpURLConnection/HttpsURLConnection. In this article we use HttpsURLConnection.
Permission
To be able to access Internet and use network API in Android, application must request permission android.permission.INTERNET
in AndroidManifest.xml.
<uses-permission android:name = "android.permission.INTERNET"/>
Using HttpsURLConnection to read data over network
HttpsURLConnection
is derived from HttpURLConnection
and indirectly from URLConnection. To get HttpsURLConnection
instance, what you need to do:
- Create URL instance.
- Call openConnection() method of URL to get
URLConnection
instance. - Typecast
URLConnection
instance into HttpsURLConnection
. Make sure you actually use HTTPS protocol (use https:// in url). - Initialize
HttpsURLConnection
and call connect() to start open connection. - Read data with getInputStream() or write data with getOutputStream(). Both method will implicitly call connect() if you have not called it.
private HttpsURLConnection openHttps(String a_url) throws IOException
{
URL url = new URL(a_url);
HttpsURLConnection httpsconn=(HttpsURLConnection) url.openConnection();
return httpsconn;
}
private HttpsURLConnection download(String screen_name) throws IOException
{
return openHttps(
"https://api.twitter.com/1/statuses/"+
"user_timeline/"+screen_name+".json");
}
To start read data from HttpsURLConnection
, you call getInputStream()
and do I/O operation on InputStream
instance returned by this method.
private String readStream(InputStream ins) throws IOException
{
InputStreamReader isr = new InputStreamReader(ins);
int charRead;
StringBuilder str = new StringBuilder();
char[] inputBuffer = new char[1024];
while ((charRead = isr.read(inputBuffer,0, 1024))>0)
{
str.append(String.copyValueOf(
inputBuffer, 0, charRead));
}
ins.close();
return str.toString();
}
Move I/O operation outside UI thread
I/O operations mostly are blocking operations. They are usually very slow and block thread execution until they complete. Android application has one main thread called UI thread where GUI updates dan input interaction takes place. If your application is doing intensive operations inside UI thread, it blocks UI thread. When UI thread execution blocked, application cannot update screen nor receive input from user. In user perspective, application seems stuck. This is not good.
Android puts restriction on how long application freeze (usually around 5 seconds). If your application cannot complete computation under 5 seconds, your application will be considered freeze and Android will display Application Not Responsive (ANR) dialog to inform user if they would like to wait application to complete or shut it down. It is important to make sure that you move slow I/O operations, such as reading data from network, outside UI thread.
Fortunately, Android has made our life easier. There are many ways to address this problem. You can use Thread, Handler or AsyncTask. For doing short-lived slow I/O operations such as reading data from network, it is more appropriate to use AsyncTask to solve this problem. To use AsyncTask, you must subclass it and implements its abstract method doInBackground(). This is where you put your slow operations. It runs outside UI thread so you must ensure that you always synchronize access to resource shared between both thread. If you can completely isolate them from need to share resources, it's better.
You can also optionally override onPreExecute() and onPostExecute() which executed before and after doInBackground()
respectively. Both methods will be executed inside UI thread so it is safe to call any methods which affect GUI element.
private class TwitterStatusesTask extends AsyncTask<String,Void,Void>
{
public ArrayList<twitterstatuses.status> statuses=null;
@Override
protected void onPostExecute(Void result)
{
StatusAdapter statAdapt=new StatusAdapter();
statAdapt.statuses=statuses;
ListView lstvw=(ListView)findViewById(R.id.listView1);
lstvw.setAdapter(statAdapt);
super.onPostExecute(result);
}
@Override
protected Void doInBackground(String... screen_name)
{
TwitterStatuses twtr=new TwitterStatuses();
statuses=twtr.get(screen_name[0]);
return null;
}
}
Read JSON data
JSON, JavaScript Object Notation, is lightweight data exchange format for network. JSON's advantages lie in its compact structure which require less storage and it is easy to parse because JSON actually is object representation in JavaScript code.
Android SDK provide libraries to handle JSON, so it is easy for Android developer to read JSON data. Example of JSON data is as follows:
{"ids":[{"id":"12345"},{"id":"67890"}]}
JSON data use {} and []. Where is the difference? {} construct is used to represent object (JSONObject) while [] is to define array (JSONArray). To read JSON data above:
JSONObject jsonObj=new JSONObject(
"{\"ids\":[{\"id\":\"12345\"},"+
"{\"id\":\"67890\"}]}");
JSONArray ids=
jsonObj.getJSONArray("ids");
JSONObject id0=ids.getJSONObject(0);
JSONObject id1=ids.getJSONObject(1);
int id00=id0.getInt("id");
int id01=id1.getInt("id");
Display I/O progress indication
Network I/O operations takes time. It is good practice to show visual indication that there is ongoing operation take place. For network I/O operation, sometime we do not know how long it is going to take. To show visual indication that user action is already processed but not completed yet, application can show waiting animation on onPreExecute()
of AsyncTask and hide it on onPostExecute()
.
If length of operations is known, you can call publishProgress() inside doInBackground()
to indicate operations progress. Then implement onProgressUpdate() to make visual indication visible.
@Override
protected void onPreExecute()
{
ProgressBar progress=(ProgressBar)findViewById(R.id.progressBar1);
progress.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected void onPostExecute(Void result)
{
ProgressBar progress=(ProgressBar)findViewById(R.id.progressBar1);
progress.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
Using the code
To use source code, just copy source code into Eclipse IDE workspace. Add new project and point it to existing code.