This tutorial explains, how to integrate twitter in android application. The example below using twitter4j java library for login to twitter and allows to post text and image in users twitters timeline. This application involves following steps
- Download twitter4j jar file
- Create a new application in Twitter developer console
- Design your application user interface
- Allow user to login to twitter and get authentication token
- Save the token for further use
- Post text or image content on twitter timeline
1. Download Twitter SDK
Twitter4J is an unofficial Java library for the Twitter API. With Twitter4J, you can easily integrate your Java application with the Twitter service. Note that twitter4j is an unofficial library.
You need to download this library before you can start integrating twitter on android. Download here.
2. Create New App in Twitter console
- Visit the below link to login to twitter developer console and login with your credentials
https://dev.twitter.com/apps - You will see a console as shown in the screenshot below. Here you can see list of applications created on twitter. For our example let us create a new application by clicking on the “Create a new application” button.
- Fill the required application details like name, description, website link and callback url. Call back url is optional, so can be left blank. And move next.
- Now we are done. You can see your app console as shown in the screenshot below. For twitter integration in android we require consumer secret and consumer key.
3. Create New Android Application
Now we are ready to start write sample application to integrate twitter4j sdk in android. Create a new project and add twitter4j-core-4.0.2.jar
to libs folder.
In this example, we have two activities. MainActivity and WebView activity. The MainActivity uses a simple layout that allows user to login to Twitter, and after login user can share message on twitter. The WebViewActivity shows user a login screen through which user can login to twitter by supplying twitter credentials. Once user is authenticated, it will be redirected to the MainActivity with the oAuth response.
Let us have a look into applications layout files.
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/activity_vertical_margin" > <RelativeLayout android:id="@+id/login_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:visibility="visible" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="@string/login_instructions" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="#0080B4" /> <Button android:id="@+id/btn_login" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="#0080B4" android:text="@string/btn_login" android:textColor="#fff" /> </RelativeLayout> <LinearLayout android:id="@+id/share_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:visibility="gone" > <TextView android:id="@+id/user_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="10dp" android:text="@string/hello" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="#0080B4" /> <ImageView android:id="@+id/imageView" android:layout_width="fill_parent" android:layout_height="150dp" android:scaleType="centerCrop" android:src="@drawable/lakeside_view" /> <EditText android:id="@+id/share_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:background="#cceaf3" android:hint="@string/share_instructions" android:inputType="textMultiLine" android:minLines="5" android:padding="10dp" /> <Button android:id="@+id/btn_share" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:background="#0080B4" android:text="@string/btn_share" android:textColor="#fff" /> </LinearLayout> </LinearLayout>
The above layout is being used in MainActivity.java. Below is the layout for WebViewActivity.java
activity_webview.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/urlContainer" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <WebView android:id="@+id/webView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/urlContainer" /> </LinearLayout>
The above layout files using few of the strings which are defined in strings.xml
. This file also contains the mandatory twitter parameters. Please do paste your own twitter consumer key and consumer secret obtained from twitter developer console (Step-1)
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Strings used in app ui--> <string name="app_name">TwitterShare</string> <string name="action_settings">Settings</string> <string name="hello">Hello, </string> <string name="login_instructions">Login to twiter</string> <string name="share_instructions">Enter share message</string> <string name="btn_login">Login to Twitter</string> <string name="btn_share">Share</string> <!-- Twitter Configurations --> <string name="twitter_callback">http://javatechig.android.app</string> <string name="twitter_consumer_key">YOUR_CONSUMER_KEY_HERE</string> <string name="twitter_consumer_secret">YOUR_CONSUMER_SECRET_HERE</string> <string name="twitter_oauth_verifier">oauth_verifier</string> <!-- End Configurations --> </resources>
4. Application Manifest Permissions
In the above two steps, we have declared the layout files and the strings used in the application. Before we getting into the massive piece of activity code, let us have a look into our application Manifest file. In this file, we have declared both the activities used in this application. Note, this application needs android.permission.INTERNET
permission and so lets declare it.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.twittershare" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" /> <!-- Permission - Internet Connect --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Network State Permissions --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.twittershare.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="t4jsample" android:scheme="oauth" /> </intent-filter> </activity> <activity android:name="com.example.twittershare.WebViewActivity" android:label="@string/app_name" /> </application> </manifest>
MainActivity.java
package com.example.twittershare; import java.io.InputStream; import twitter4j.StatusUpdate; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.User; import twitter4j.auth.AccessToken; import twitter4j.auth.RequestToken; import twitter4j.conf.Configuration; import twitter4j.conf.ConfigurationBuilder; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.StrictMode; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { /* Shared preference keys */ private static final String PREF_NAME = "sample_twitter_pref"; private static final String PREF_KEY_OAUTH_TOKEN = "oauth_token"; private static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret"; private static final String PREF_KEY_TWITTER_LOGIN = "is_twitter_loggedin"; private static final String PREF_USER_NAME = "twitter_user_name"; /* Any number for uniquely distinguish your request */ public static final int WEBVIEW_REQUEST_CODE = 100; private ProgressDialog pDialog; private static Twitter twitter; private static RequestToken requestToken; private static SharedPreferences mSharedPreferences; private EditText mShareEditText; private TextView userName; private View loginLayout; private View shareLayout; private String consumerKey = null; private String consumerSecret = null; private String callbackUrl = null; private String oAuthVerifier = null; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* initializing twitter parameters from string.xml */ initTwitterConfigs(); /* Enabling strict mode */ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); /* Setting activity layout file */ setContentView(R.layout.activity_main); loginLayout = (RelativeLayout) findViewById(R.id.login_layout); shareLayout = (LinearLayout) findViewById(R.id.share_layout); mShareEditText = (EditText) findViewById(R.id.share_text); userName = (TextView) findViewById(R.id.user_name); /* register button click listeners */ findViewById(R.id.btn_login).setOnClickListener(this); findViewById(R.id.btn_share).setOnClickListener(this); /* Check if required twitter keys are set */ if (TextUtils.isEmpty(consumerKey) || TextUtils.isEmpty(consumerSecret)) { Toast.makeText(this, "Twitter key and secret not configured", Toast.LENGTH_SHORT).show(); return; } /* Initialize application preferences */ mSharedPreferences = getSharedPreferences(PREF_NAME, 0); boolean isLoggedIn = mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false); /* if already logged in, then hide login layout and show share layout */ if (isLoggedIn) { loginLayout.setVisibility(View.GONE); shareLayout.setVisibility(View.VISIBLE); String username = mSharedPreferences.getString(PREF_USER_NAME, ""); userName.setText(getResources ().getString(R.string.hello) + username); } else { loginLayout.setVisibility(View.VISIBLE); shareLayout.setVisibility(View.GONE); Uri uri = getIntent().getData(); if (uri != null && uri.toString().startsWith(callbackUrl)) { String verifier = uri.getQueryParameter(oAuthVerifier); try { /* Getting oAuth authentication token */ AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier); /* Getting user id form access token */ long userID = accessToken.getUserId(); final User user = twitter.showUser(userID); final String username = user.getName(); /* save updated token */ saveTwitterInfo(accessToken); loginLayout.setVisibility(View.GONE); shareLayout.setVisibility(View.VISIBLE); userName.setText(getString(R.string.hello) + username); } catch (Exception e) { Log.e("Failed to login Twitter!!", e.getMessage()); } } } } /** * Saving user information, after user is authenticated for the first time. * You don't need to show user to login, until user has a valid access toen */ private void saveTwitterInfo(AccessToken accessToken) { long userID = accessToken.getUserId(); User user; try { user = twitter.showUser(userID); String username = user.getName(); /* Storing oAuth tokens to shared preferences */ Editor e = mSharedPreferences.edit(); e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken()); e.putString(PREF_KEY_OAUTH_SECRET, accessToken.getTokenSecret()); e.putBoolean(PREF_KEY_TWITTER_LOGIN, true); e.putString(PREF_USER_NAME, username); e.commit(); } catch (TwitterException e1) { e1.printStackTrace(); } } /* Reading twitter essential configuration parameters from strings.xml */ private void initTwitterConfigs() { consumerKey = getString(R.string.twitter_consumer_key); consumerSecret = getString(R.string.twitter_consumer_secret); callbackUrl = getString(R.string.twitter_callback); oAuthVerifier = getString(R.string.twitter_oauth_verifier); } private void loginToTwitter() { boolean isLoggedIn = mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false); if (!isLoggedIn) { final ConfigurationBuilder builder = new ConfigurationBuilder(); builder.setOAuthConsumerKey(consumerKey); builder.setOAuthConsumerSecret(consumerSecret); final Configuration configuration = builder.build(); final TwitterFactory factory = new TwitterFactory(configuration); twitter = factory.getInstance(); try { requestToken = twitter.getOAuthRequestToken(callbackUrl); /** * Loading twitter login page on webview for authorization * Once authorized, results are received at onActivityResult * */ final Intent intent = new Intent(this, WebViewActivity.class); intent.putExtra(WebViewActivity.EXTRA_URL, requestToken.getAuthenticationURL()); startActivityForResult(intent, WEBVIEW_REQUEST_CODE); } catch (TwitterException e) { e.printStackTrace(); } } else { loginLayout.setVisibility(View.GONE); shareLayout.setVisibility(View.VISIBLE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { String verifier = data.getExtras().getString(oAuthVerifier); try { AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier); long userID = accessToken.getUserId(); final User user = twitter.showUser(userID); String username = user.getName(); saveTwitterInfo(accessToken); loginLayout.setVisibility(View.GONE); shareLayout.setVisibility(View.VISIBLE); userName.setText(MainActivity.this.getResources().getString( R.string.hello) + username); } catch (Exception e) { Log.e("Twitter Login Failed", e.getMessage()); } } super.onActivityResult(requestCode, resultCode, data); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_login: loginToTwitter(); break; case R.id.btn_share: final String status = mShareEditText.getText().toString(); if (status.trim().length() > 0) { new updateTwitterStatus().execute(status); } else { Toast.makeText(this, "Message is empty!!", Toast.LENGTH_SHORT).show(); } break; } } class updateTwitterStatus extends AsyncTask<String, String, Void> { @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(MainActivity.this); pDialog.setMessage("Posting to twitter..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); } protected Void doInBackground(String... args) { String status = args[0]; try { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.setOAuthConsumerKey(consumerKey); builder.setOAuthConsumerSecret(consumerSecret); // Access Token String access_token = mSharedPreferences.getString(PREF_KEY_OAUTH_TOKEN, ""); // Access Token Secret String access_token_secret = mSharedPreferences.getString(PREF_KEY_OAUTH_SECRET, ""); AccessToken accessToken = new AccessToken(access_token, access_token_secret); Twitter twitter = new TwitterFactory(builder.build()).getInstance(accessToken); // Update status StatusUpdate statusUpdate = new StatusUpdate(status); InputStream is = getResources().openRawResource(R.drawable.lakeside_view); statusUpdate.setMedia("test.jpg", is); twitter4j.Status response = twitter.updateStatus(statusUpdate); Log.d("Status", response.getText()); } catch (TwitterException e) { Log.d("Failed to post!", e.getMessage()); } return null; } @Override protected void onPostExecute(Void result) { /* Dismiss the progress dialog after sharing */ pDialog.dismiss(); Toast.makeText(MainActivity.this, "Posted to Twitter!", Toast.LENGTH_SHORT).show(); // Clearing EditText field mShareEditText.setText(""); } } }
WebViewActivity.java
package com.example.twittershare; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; public class WebViewActivity extends Activity { private WebView webView; public static String EXTRA_URL = "extra_url"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_webview); setTitle("Login"); final String url = this.getIntent().getStringExtra(EXTRA_URL); if (null == url) { Log.e("Twitter", "URL cannot be null"); finish(); } webView = (WebView) findViewById(R.id.webView); webView.setWebViewClient(new MyWebViewClient()); webView.loadUrl(url); } class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.contains(getResources().getString(R.string.twitter_callback))) { Uri uri = Uri.parse(url); /* Sending results back */ String verifier = uri.getQueryParameter(getString(R.string.twitter_oauth_verifier)); Intent resultIntent = new Intent(); resultIntent.putExtra(getString(R.string.twitter_oauth_verifier), verifier); setResult(RESULT_OK, resultIntent); /* closing webview */ finish(); return true; } return false; } } }
5. Output
6. Download Source Code
Download complete example source code from GitHub.