In this series we are building a Twitter client for the Android platform using the Twitter4J library. In this tutorial we will prepare our user interface elements for the app and handle signing the user into Twitter to allow access to their account.
Also available in this series:
- Creating a Twitter Client for Android: Setup & Overview
- Creating a Twitter Client for Android: Building the Interface
- Creating a Twitter Client for Android: Creating a Timeline Database
- Creating a Twitter Client for Android: Retrieving Updates Using a Service
- Creating a Twitter Client for Android: Tweeting, Retweeting, and Replying
Step 1: Authorize the App to Access the User's Twitter Account
Before we can access the user's Twitter account, we need them to sign in and grant the app permission. Open the main Activity class for your application, creating it now if Eclipse did not generate it automatically when you started the project. Alter your class declaration opening line as follows, and change the name of the class to suit your own if necessary:
public class TwitNiceActivity extends Activity implements OnClickListener
The OnClickListener will detect various button clicks. You will need the following import statements added above your class declaration, although Eclipse may have added some automatically:
import android.app.Activity; import android.os.Bundle; import android.view.View.OnClickListener;
Inside the class, add the following instance variables:
/**developer account key for this app*/ public final static String TWIT_KEY = "your key"; /**developer secret for the app*/ public final static String TWIT_SECRET = "your secret"; /**app url*/ public final static String TWIT_URL = "tnice-android:///";
Alter the Key and Secret variables to store the values you copied from your Twitter Developer account last time. Notice that the URL is an extended version of the data element we added to the Manifest, so make sure to alter it if you used a different value there. Add the following additional instance variables for connecting to Twitter:
/**Twitter instance*/ private Twitter niceTwitter; /**request token for accessing user account*/ private RequestToken niceRequestToken; /**shared preferences to store user details*/ private SharedPreferences nicePrefs; //for error logging private String LOG_TAG = "TwitNiceActivity";//alter for your Activity name
When the user grants permission, we will add the resulting data to the Shared Preferences. Each time the app runs, it will check whether these details have been set. If so it will use them to fetch the user's timeline straight away. If the details have not been set it will prompt the user to sign in and grant permission. You will need the following import statements:
import twitter4j.Twitter; import twitter4j.auth.RequestToken; import android.content.SharedPreferences;
Find out if the user has already authorized the app
In the Activity onCreate method, after the call to the superclass method, add the following code:
//get the preferences for the app nicePrefs = getSharedPreferences("TwitNicePrefs", 0); //find out if the user preferences are set if(nicePrefs.getString("user_token", null)==null) { //no user preferences so prompt to sign in setContentView(R.layout.main); } else { //user preferences are set - get timeline setupTimeline(); }
Here we get a reference to the application Shared Preferences object to establish whether the user has already granted the app permission or not. The "user_token" preferences string is going to store the access token we use for accessing Twitter, so if it has already been set, we know the user has previously signed in for the app. If the preferences have not been set, we need to prompt the user to sign into Twitter, which we will do in the "if" statement - for the moment we simply set the main content view.
In the "else" block we take care of users who have already signed in and authorized the app. Here we call a helper method named "setupTimeline" which we will implement in the next tutorial.
Handle the First Run
Let's create our main layout, which we have set in the "if" statement. Normally Eclipse creates a file at "res/layout/main.xml" automatically, if not you can create it yourself by right-clicking the layout folder in the Package Explorer (or selecting it and then choosing the File menu), then choosing "New" and "File." Open the main layout file and enter the following XML code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Welcome to TwitNice!" android:textStyle="bold" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="You need to sign into Twitter to authorize the app" /> <Button android:id="@+id/signin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Sign In" /> </LinearLayout>
This is a LinearLayout with two text-fields and a button. The text-fields are simply informative, while the button will take the user to the Twitter sign-in Web page. The button has an ID attribute so that we can identify it in the Java code.

Now back to our onCreate method for the main app Activity to implement signing in first time users. You will need the following import:
import android.util.Log;
Inside the "if" block, after the line in which we set the main content view, add the following:
//get a twitter instance for authentication niceTwitter = new TwitterFactory().getInstance(); //pass developer key and secret niceTwitter.setOAuthConsumer(TWIT_KEY, TWIT_SECRET);
Here we create an instance of the Twitter class from the Twitter4J library, which we already declared as an instance variable. This class is required for pretty much everything we do with Twitter. To verify our credentials, we pass the Key and Secret from the developer interface where the app was registered, for both of which we created class constants. Next we need to get a request token from the Twitter object so that we can attempt to authorize the app for the user's account:
//try to get request token try { //get authentication request token niceRequestToken = niceTwitter.getOAuthRequestToken(TWIT_URL); } catch(TwitterException te) { Log.e(LOG_TAG, "TE " + te.getMessage()); }
We are here attempting to instantiate the request token for which we created an instance variable. The method can throw an exception, so we surround it in a try block and output an error message to the Android Log if the exception is thrown. Notice that the code uses the "LOG_TAG" constant we created - you can see the resulting messages in the Eclipse LogCat panel.
Send to Twitter
To finish the "if" block, set up a click listener for the sign-in button we included in our "main.xml" layout file:
//setup button for click listener Button signIn = (Button)findViewById(R.id.signin); signIn.setOnClickListener(this);
The click listener for the button is the Activity class itself, so we now need to implement the onClick method anywhere in the class file:
/** * Click listener handles sign in and tweet button presses */ public void onClick(View v) { //find view switch(v.getId()) { //sign in button pressed case R.id.signin: //take user to twitter authentication web page to allow app access to their twitter account String authURL = niceRequestToken.getAuthenticationURL(); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authURL))); break; //other listeners here default: break; } }
The method uses a switch statement to tailor what happens to particular button presses. We will be adding a case statement for another button later, but for the moment all we need is the sign-in process. The code retrieves the authentication URL from the Twitter request token object, then opens the page in the Web browser.
Don't worry too much about how these Twitter4J methods are implemented. This is simply the process you need to follow if you use the API. Not having to concern yourself with the implementation details of connecting to Twitter is one of the main benefits to using an external library.
Return From Sign-In
We need to handle what will happen when the user is returned to the app after signing into Twitter to authorize it. When the user signs in successfully, Twitter will return them along with some data to verify and facilitate the app's access to their account. The "onNewIntent" method will fire, so let's implement it now:
/* * onNewIntent fires when user returns from Twitter authentication Web page */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); //get the retrieved data Uri twitURI = intent.getData(); //make sure the url is correct if(twitURI!=null && twitURI.toString().startsWith(TWIT_URL)) { //is verifcation - get the returned data String oaVerifier = twitURI.getQueryParameter("oauth_verifier"); } }
The method retrieves the verification data from Twitter, which we will later use to access the user's tweets. So that we only need to carry out the sign-in process once, we store the required data in the application Shared Preferences. Still inside the "if" statement, add the following:
//attempt to retrieve access token try { //try to get an access token using the returned data from the verification page AccessToken accToken = niceTwitter.getOAuthAccessToken(niceRequestToken, oaVerifier); //add the token and secret to shared prefs for future reference nicePrefs.edit() .putString("user_token", accToken.getToken()) .putString("user_secret", accToken.getTokenSecret()) .commit(); //display the timeline setupTimeline(); } catch (TwitterException te) { Log.e(LOG_TAG, "Failed to get access token: " + te.getMessage()); }
This is another method that can cause an exception to be thrown. The code inside the try block first retrieves the Access Token from Twitter using the data returned from the Web page. Then it uses the Shared Preferences object to store the Token and Secret necessary for Twitter access. Finally, the code calls the method to display the timeline, which we have not yet implemented.
If you want to test the sign in process just now, provide the "setupTimeline" method, simply including a message output to the Log, for example:
private void setupTimeline() { Log.v(LOG_TAG, "setting up timeline"); }
We will implement the method fully in the following tutorials.
Step 2: Create the Application Layouts
Now that we have handled signing users in the first time they run the application, we can turn to the user interface for the app as it runs subsequently. We will be using various resources in the user interface design for this app, including drawables, colors, and layouts. The layout XML files will refer to drawable resources which we will create in the next step. Don't worry if Eclipse alerts you to errors because the resources are not yet present. When you create the layout files, simply notice the references to resources you still have to create.
The app is going to use four layout files, one of which ("main.xml") we have already created for the sign-in screen which only appears on first run. We also need layouts to define the appearance of the main timeline, the Tweet screen and each update within the timeline. In each layout file, you will notice that many of the elements have ID attributes. This is so that we can refer to these elements within the Java application code, particularly when handling user interaction.
Timeline
The timeline layout is going to be the main interface users see when they launch the app, after authorizing it. The home timeline shows the list of recent tweets from those accounts the user follows. At the top of the screen, the user will see a header and the Tweet button, for switching to the Tweet screen to send a tweet. The content of each update in the home timeline will be defined in a separate layout file, but in the timeline layout we will take care of the container for the list of updates as a whole.
Create a new file in your "res/layout" folder, with "timeline.xml" as the file-name. Open the new file and add the following outline, which we will extend:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0" > <TableRow> </TableRow> </TableLayout> <ListView android:id="@+id/homeList" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
The View is defined by a LinearLayout. Inside this we have a TableLayout and a ListView. We will be adding elements inside the TableRow next. The ListView is going to hold the list of update tweets to display within the user's home timeline. The list will be populated with those tweets when the application executes. For the moment we simply define the View that will hold them.
Add content inside the TableLayout TableRow element:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="15dp" android:layout_marginTop="4dp" android:background="@drawable/homebg" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Home" android:textColor="#ffffff" android:textSize="25sp" android:textStyle="bold" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:background="#ffffff" android:src="@drawable/home" /> </LinearLayout>
This creates a header for the home timeline. The text "Home" is laid out next to a drawable resource named "home". Notice that the section also has a background which is another drawable resource named "homebg".
Next add the tweet button, still inside the TableRow but after the LinearLayout you just added:
<LinearLayout android:id="@+id/tweetbtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:layout_marginRight="3dp" android:layout_marginTop="2dp" android:background="@drawable/tweetbtnbg" android:clickable="true" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:text="Tweet" android:textColor="#000000" android:textSize="25sp" android:textStyle="bold" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tweet" /> </LinearLayout>
As you can see, this is similar to the Home header, but in this case the View is going to function as a button - the LinearLayout has its "clickable" attribute set to true. The button will include the text "Tweet" displayed next to an image. When users click this button they will be taken to the Tweet screen.
At the moment when you choose the Graphical Layout tab for your timeline XML in Eclipse, you won't see much. Once we have created the drawables and the update layout file, it will look like this:

Since the content of the timeline is only built at runtime, you cannot really see what the interface will look like until you are able to run the app.
Update
We are going to use a layout file to model a single update within the home timeline. Create a new file in your layout directory, naming it "update.xml". Enter the following outline:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingRight="7dp" android:paddingBottom="3dp" android:orientation="horizontal" > <ImageView android:id="@+id/userImg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="@drawable/profilebg" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> </LinearLayout>
The layout contains a section for the profile image of the account whose tweet is being displayed, then a section for the tweet content. Inside the second LinearLayout element we will add the tweet content and the buttons for retweeting/replying. Start with the tweet content:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/userScreen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:textColor="@color/control_two" android:textStyle="bold" /> <TextView android:id="@+id/updateTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:textColor="#cccccc" android:textStyle="italic" /> </LinearLayout> <TextView android:id="@+id/updateText" android:layout_width="wrap_content" android:layout_height="80dp" android:layout_marginBottom="5dp" android:autoLink="all" android:textColorLink="@color/control_one" android:textColor="#ffffff" />
Each tweet includes the screen name of the tweeting account, the time the tweet was sent, and the tweet itself. Each TextView has an ID attribute, as the Java code is going to map the incoming tweet data to these Views when the app runs. The final TextView, for the tweet text itself, has the "autoLink" attribute set so that users can click links in the tweets. The user screen name view is also clickable, so that users can browse to the profile page of each account in their timeline. Notice that these Views also include references to color resources we have not yet created.
Now let's add the retweet and reply buttons, after the TextView we just added:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:orientation="horizontal" > <Button android:id="@+id/retweet" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:background="@drawable/updatebtnbg" android:textColor="#ffffff" android:text="retweet" /> <Button android:id="@+id/reply" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/updatebtnbg" android:textColor="#ffffff" android:text="reply" /> </LinearLayout>
Every tweet in the timeline is going to be accompanied by these buttons, each with a little text and a background. Here is a snapshot of a single update in the finished app.

Tweet
Now we turn to the other main screen in our app, the Tweet screen. Create another new file in your Layout folder, naming it "tweet.xml". Enter the following outline:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#333333" android:paddingLeft="3dp" android:paddingRight="3dp" android:paddingBottom="5dp" android:orientation="vertical" > <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0" > <TableRow > <LinearLayout android:id="@+id/homebtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="15dp" android:layout_marginTop="4dp" android:background="@drawable/homebtnbg" android:clickable="true" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Home" android:textColor="#ffffff" android:textSize="25sp" android:textStyle="bold" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:background="#ffffff" android:src="@drawable/home" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:layout_marginRight="3dp" android:layout_marginTop="2dp" android:background="@drawable/tweetbtnbg" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:text="Tweet" android:textColor="#000000" android:textSize="25sp" android:textStyle="bold" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/tweet" /> </LinearLayout> </TableRow> </TableLayout> </LinearLayout>
We will add more elements after the TableLayout next. Don't worry about adding all of this code at once - if you compare it to the timeline layout above you'll see that it's almost identical. The top section with the Home header and Tweet button will appear similarly in both the home timeline and Tweet screens. Apart from some small cosmetic differences to distinguish the two, the main difference is that in the Tweet screen, the Home header functions as a button to take the user back to their home timeline, whereas in the timeline layout, the Tweet View functions as a button.
After the TableLayout, add the following:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:text="What do you want to say?" /> <EditText android:id="@+id/tweettext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:lines="5" android:singleLine="false" /> <Button android:id="@+id/dotweet" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/tweetbtnbg" android:text="send" />
This is the main content for the Tweet screen. A small amount of informative text precedes the editable text-field for the user to enter their tweet text, then we have a button for them to go ahead and send the tweet. Once we create our drawable resources, in the Graphical Layout tab for the tweet layout you will see something like this:

Step 3: Create the Application Drawables
Now let's create the visual elements in our interface, most of which we have already referred to in our layout resources. Some of our drawables will be defined in XML files and some will be created outside the application, using a graphic design or image editing program. You can of course alter any of the visual elements you like, but I would recommend starting with the steps outlined in this tutorial, then making changes once you understand how the various ingredients relate to one another.
Images
For this application we are using three images created outside Eclipse, for the app icon, the home timeline, and the tweet button. You can create your own versions of these if you like, or not bother using images at all if you prefer. The home timeline is a simple drawing, while the tweet button and app icon use the official Twitter resources, which also include retweet, reply and favorite icons.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
When you have your drawables ready, copy them into your application workspace folder, in "res/drawables-*". Eclipse should have created three drawables folders in your project workspace, for low, medium, and high resolution devices. The images must be saved as "ic_launcher" for the icon, "home" and "tweet" for the buttons. Make sure each image is saved with the same name in each folder, e.g. the tweet image could be named "tweet.png" in all three folders, although the images in each folder are actually different sizes, to suit the different resolutions.
You may need to instruct Eclipse to refresh your workspace before your code can refer to the new images successfully. To do so, select the project in the Package Explorer, right-click or choose File, then Refresh.
Colors
Other than black, white, and gray, the app interface mainly uses two colors, shades of green and blue. Let's define these as color resources. In Eclipse, create a new file in the "res/values" directory named "colors.xml":

In the colors XML file, enter the following code to define the two main colors in the app:
<resources> <color name="control_one">#FF006699</color> <color name="control_two">#FF009933</color> <color name="control_one_opaque">#66006699</color> <color name="control_two_opaque">#66009933</color> </resources>
This code indicates two colors plus opaque versions of each. Now if you want to change the color scheme for the application buttons, you can do it in a single location.
Backgrounds
Finally, let's get our backgrounds created to complete the user interface design. We will run through each drawable file in turn, but remember that you need to copy every one into all three drawable folders in your app's resources directory.
Create a new file in your drawables folder(s) named "homebg.xml" with the following content:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:startColor="#ff000000" android:endColor="#ff333333" android:angle="90" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> </shape>
This defines a simple drawable shape with padding and a gradient fill. If you look back at your timeline XML layout code, you will see this drawable referred to as the background for a LinearLayout.
Create another new file named "homebtnbg.xml" in your drawables with the following content:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:startColor="#ff000000" android:endColor="#ff121212" android:angle="90" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> </shape>
This background is used for the Home button in the Tweet screen. Next create a file named "profilebg.xml" with the following content:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:startColor="#cc666666" android:endColor="#33666666" android:angle="90" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> <corners android:radius="2dp" /> </shape>
This time we define rounded corners as well as padding and gradient fill. This background is for displaying behind the profile images in the timeline.
The final two drawables are slightly more complex. For the Tweet button and the buttons in each update (for replying or retweeting) we are going to define different appearances for selection states so that the buttons change in appearance when the user presses them. Create a file named "tweetbtnbg.xml" with the following content:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:startColor="@color/control_two_opaque" android:endColor="@color/control_one_opaque" android:angle="90" /> <stroke android:width="2dp" android:color="#66ffffff" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> <corners android:radius="2dp" /> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:startColor="@color/control_two" android:endColor="@color/control_one" android:angle="90" /> <stroke android:width="2dp" android:color="#ffffffff" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> <corners android:radius="2dp" /> </shape> </item> </selector>
This code defines two slightly different shapes, one for when the button is pressed. The only difference between them is in the colors, which are defined as the color resources we created. Finally, create a similar file named "updatebtnbg.xml" with the following content:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:angle="90" android:endColor="@color/control_two_opaque" android:startColor="@color/control_one_opaque" /> <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp" /> <corners android:radius="2dp" /> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true"> <gradient android:angle="90" android:endColor="@color/control_two" android:startColor="@color/control_one" /> <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp" /> <corners android:radius="2dp" /> </shape> </item> </selector>
Once you have these copied into each of your drawables folders, you can choose to alter them to suit different screen sizes if you wish. Your drawable resources should look something like this, with all files in all three folders:

Eclipse should now stop displaying error messages for your layout files, as all referenced resources are present.
Next
Now our user interface design is complete! In the next tutorial we will create a database to store the update tweets, then use an Adapter to map these updates to the View elements so that the user can see them.
Comments