http://blog.blundell-apps.com/sending-a-tweet/
Implemented this myself so thought I would share.
This isn’t the prettiest solution but it gives you all the facts and is nice an quick.
I’ve kept it all in one Activity to try and give you the overview you can deal with the OO later yourself.
Source file downloads are at the bottom of this post.
Ok What we are going to do:
Authorise your app to use a users twitter account.
Send a tweet from this account.
Workflow:
User presses Login Button
Checks if user has logged in before
Twitter webpage is opened
User logins in to twitter
App is then allowed to post tweets
Users presses Tweet Button
Tweet is sent to Twitter
Simple!
A sneak preview of what it’ll look like:
Setup:
You need to create a Twitter Application (takes 2 mins) on the Twitter site: https://dev.twitter.com/apps/
Ensure
Application Type: Browser
Permissions: Read & Write
Callback URL; doesnt matter put anything http://google.com
Next you need the Twitter4j Jar, this does all the hard work behind the scenes.
You can download it here: Twitter4J jar
Unzip it.
You then have to add it to your project.
Eclipse:
Right Click on your project > Properties > Java Build Path > Add External Jars > twitter4j-core-android-2.2.3.jar> OK
Easy!
Ok now to the coding!
First your manifest needs to be able to receive the twitter call back from the browser, it also needs the activity to be single instance:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blundell.tut.ttt"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="4" />
<!-- used by twitter integration -->
<uses-permission
android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".TweetToTwitterActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<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:scheme="tweet-to-twitter-blundell-01-android" />
</intent-filter>
</activity>
</application>
</manifest>
Then I’ve compacted it all into a single Activity with comments so you should be able to understand what is going on:
package com.blundell.tut.ttt;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
public class TweetToTwitterActivity extends Activity {
private static final String TAG = "Blundell.TweetToTwitterActivity";
/** Name to store the users access token */
private static final String PREF_ACCESS_TOKEN = "accessToken";
/** Name to store the users access token secret */
private static final String PREF_ACCESS_TOKEN_SECRET = "accessTokenSecret";
/** Consumer Key generated when you registered your app at https://dev.twitter.com/apps/ */
private static final String CONSUMER_KEY = "yourConsumerKey";
/** Consumer Secret generated when you registered your app at https://dev.twitter.com/apps/ */
private static final String CONSUMER_SECRET = "yourConsumerSecret"; // XXX Encode in your app
/** The url that Twitter will redirect to after a user log's in - this will be picked up by your app manifest and redirected into this activity */
private static final String CALLBACK_URL = "tweet-to-twitter-blundell-01-android:///";
/** Preferences to store a logged in users credentials */
private SharedPreferences mPrefs;
/** Twitter4j object */
private Twitter mTwitter;
/** The request token signifies the unique ID of the request you are sending to twitter */
private RequestToken mReqToken;
private Button mLoginButton;
private Button mTweetButton;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "Loading TweetToTwitterActivity");
setContentView(R.layout.main);
// Create a new shared preference object to remember if the user has
// already given us permission
mPrefs = getSharedPreferences("twitterPrefs", MODE_PRIVATE);
Log.i(TAG, "Got Preferences");
// Load the twitter4j helper
mTwitter = new TwitterFactory().getInstance();
Log.i(TAG, "Got Twitter4j");
// Tell twitter4j that we want to use it with our app
mTwitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
Log.i(TAG, "Inflated Twitter4j");
mLoginButton = (Button) findViewById(R.id.login_button);
mTweetButton = (Button) findViewById(R.id.tweet_button);
}
/**
* Button clickables are declared in XML as this projects min SDK is 1.6</br> </br>
* Checks if the user has given this app permission to use twitter
* before</br> If so login and enable tweeting</br>
* Otherwise redirect to Twitter for permission
*
* @param v the clicked button
*/
public void buttonLogin(View v) {
Log.i(TAG, "Login Pressed");
if (mPrefs.contains(PREF_ACCESS_TOKEN)) {
Log.i(TAG, "Repeat User");
loginAuthorisedUser();
} else {
Log.i(TAG, "New User");
loginNewUser();
}
}
/**
* Button clickables are declared in XML as this projects min SDK is 1.6</br> </br>
*
* @param v the clicked button
*/
public void buttonTweet(View v) {
Log.i(TAG, "Tweet Pressed");
tweetMessage();
}
/**
* Create a request that is sent to Twitter asking 'can our app have permission to use Twitter for this user'</br>
* We are given back the {@link mReqToken}
* that is a unique indetifier to this request</br>
* The browser then pops up on the twitter website and the user logins in ( we never see this informaton
* )</br> Twitter then redirects us to {@link CALLBACK_URL} if the login was a success</br>
*
*/
private void loginNewUser() {
try {
Log.i(TAG, "Request App Authentication");
mReqToken = mTwitter.getOAuthRequestToken(CALLBACK_URL);
Log.i(TAG, "Starting Webview to login to twitter");
WebView twitterSite = new WebView(this);
twitterSite.loadUrl(mReqToken.getAuthenticationURL());
setContentView(twitterSite);
} catch (TwitterException e) {
Toast.makeText(this, "Twitter Login error, try again later", Toast.LENGTH_SHORT).show();
}
}
/**
* The user had previously given our app permission to use Twitter</br>
* Therefore we retrieve these credentials and fill out the Twitter4j helper
*/
private void loginAuthorisedUser() {
String token = mPrefs.getString(PREF_ACCESS_TOKEN, null);
String secret = mPrefs.getString(PREF_ACCESS_TOKEN_SECRET, null);
// Create the twitter access token from the credentials we got previously
AccessToken at = new AccessToken(token, secret);
mTwitter.setOAuthAccessToken(at);
Toast.makeText(this, "Welcome back", Toast.LENGTH_SHORT).show();
enableTweetButton();
}
/**
* Catch when Twitter redirects back to our {@link CALLBACK_URL}</br>
* We use onNewIntent as in our manifest we have singleInstance="true" if we did not the
* getOAuthAccessToken() call would fail
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i(TAG, "New Intent Arrived");
dealWithTwitterResponse(intent);
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "Arrived at onResume");
}
/**
* Twitter has sent us back into our app</br>
* Within the intent it set back we have a 'key' we can use to authenticate the user
*
* @param intent
*/
private void dealWithTwitterResponse(Intent intent) {
Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) { // If the user has just logged in
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
authoriseNewUser(oauthVerifier);
}
}
/**
* Create an access token for this new user</br>
* Fill out the Twitter4j helper</br>
* And save these credentials so we can log the user straight in next time
*
* @param oauthVerifier
*/
private void authoriseNewUser(String oauthVerifier) {
try {
AccessToken at = mTwitter.getOAuthAccessToken(mReqToken, oauthVerifier);
mTwitter.setOAuthAccessToken(at);
saveAccessToken(at);
// Set the content view back after we changed to a webview
setContentView(R.layout.main);
enableTweetButton();
} catch (TwitterException e) {
Toast.makeText(this, "Twitter auth error x01, try again later", Toast.LENGTH_SHORT).show();
}
}
/**
* Allow the user to Tweet
*/
private void enableTweetButton() {
Log.i(TAG, "User logged in - allowing to tweet");
mLoginButton.setEnabled(false);
mTweetButton.setEnabled(true);
}
/**
* Send a tweet on your timeline, with a Toast msg for success or failure
*/
private void tweetMessage() {
try {
mTwitter.updateStatus("Test - Tweeting with @Blundell_apps #AndroidDev Tutorial using #Twitter4j http://blog.blundell-apps.com/sending-a-tweet");
Toast.makeText(this, "Tweet Successful!", Toast.LENGTH_SHORT).show();
} catch (TwitterException e) {
Toast.makeText(this, "Tweet error, try again later", Toast.LENGTH_SHORT).show();
}
}
private void saveAccessToken(AccessToken at) {
String token = at.getToken();
String secret = at.getTokenSecret();
Editor editor = mPrefs.edit();
editor.putString(PREF_ACCESS_TOKEN, token);
editor.putString(PREF_ACCESS_TOKEN_SECRET, secret);
editor.commit();
}
}
If you find this helpful please say thanks
Happy Coding
And any questions just ask!
The eclipse project src as promised:
—> TweetToTwitter <---





82 Comments
Hello,
Program working brilliantly, posted to Twitter first time, please can you tell me how I can incorporate this into my existing application? Is there a class that you can create from this app that I can call from my main app?
Cheers
Yeah you can just create this as your TwitterActivity and start it with an Intent
Thanks man ….. nice tutorial
Hi thanks for tutorials, I am new to android, I have tried your code but it showing me problem with login, it is showing me toast at line 116.
Could you please help me to solve this it’s very urgent.
Hi, i changed consumer key and consumer secrete key but i am still getting error in your project. and error is -
java.lang.VerifyError: com.blundell.tut.ttt.TweetToTwitterActivity
where as i have put all keys correctly. and also check for second project but getting same error. so please tell me what the problem is exactly.
and i also don’t find field application type(client , browser) on dev.twitter.com web site. so please help.
Thank you very much for this tutorial. Good Job.
It’s useful, thanks a lot.
I have followed the procedure completely, included all the libraries. Still i am getting this error:
01-04 11:48:58.016: E/dalvikvm(328): Could not find class ‘twitter4j.http.AccessToken’, referenced from method com.ecs.android.sample.twitter.TwitterUtils.isAuthenticated
01-04 11:48:58.067: E/AndroidRuntime(328): java.lang.NoClassDefFoundError: twitter4j.http.AccessToken
01-04 11:48:58.067: E/AndroidRuntime(328): at com.ecs.android.sample.twitter.TwitterUtils.isAuthenticated(TwitterUtils.java:18)
01-04 11:48:58.067: E/AndroidRuntime(328): at com.ecs.android.sample.twitter.AndroidTwitterSample.updateLoginStatus(AndroidTwitterSample.java:72)
01-04 11:48:58.067: E/AndroidRuntime(328): at com.ecs.android.sample.twitter.AndroidTwitterSample.onResume(AndroidTwitterSample.java:68)
Somethings wrong with your classpath, you need to export the twitter4j jar with your app when it is deployed
Thanks!! Great work!
Thanks a lot for the tutorial. Twitter4j really lacks android example.
This is very helpful.
Its like you read my mind! You appear to know a lot approximately this, such as you wrote the guide in it or something. A fantastic read.
I’ll certainly be back.
H? I want to post tweet from android phone When I go to https://dev.twitter.com/apps/ page , I don’t see Application Type. So, The application give me error
hi I tried your sourcecode above but I got this error when I run it to my nexus s.
10-31 18:12:15.699: E/AndroidRuntime(7881): FATAL EXCEPTION: main
10-31 18:12:15.699: E/AndroidRuntime(7881): java.lang.VerifyError: edu/rivera/augmentwit/MainActivity
10-31 18:12:15.699: E/AndroidRuntime(7881): at java.lang.Class.newInstanceImpl(Native Method)
10-31 18:12:15.699: E/AndroidRuntime(7881): at java.lang.Class.newInstance(Class.java:1319)
10-31 18:12:15.699: E/AndroidRuntime(7881): at android.app.Instrumentation.newActivity(Instrumentation.java:1053)
Hmm verify error is something like the app didn’t install correctly, or class declarations are incorrect, i.e. AndroidManifest or packages. The source code works!
Dear Blundell,
Its working fine for me.
How can we implement whole process with help of WebView, Please explain wholw process to implement it.
Dear Blundell,
Great tutorial,
I am able to tweet my custom tweet from above program.
How Can it will be implement whole process with help of WebView?
Hello blundell,
Nice blog ..!!really helpful in getting started..!!
The only issue is every time i get registered as a new user.
so here is how it should have worked according to code,u first click on login button for the first time,then registers with twitter,then comes back to the activity,tweet button should be enabled..have i done it rightly??
also now if i press login button i should be detected as a “repeat user” and should be able to tweet..either ways all what is happening is i am just getting registered,i am not able to go back to the screen and tweet..can u help me get it right??
There is no registration involved, perhaps take a second look at how you are signing in.
This was an extremely helpful post. Probably the first complete *and working* example of Twitter OAuth in an Android app.
Thank you very much!
There is no action on the button when i pressed them, please help me out. Thanks
Hi UI check you have set your onClickListeners correctly, or have it defined in the XML layout file
hey thanks for tutorial
see i have used your code but on ics and jellybean it shows fouce close when you press login button…
I want to develop app in which user can twitte that XYZ listening XYZ file on XYZ app..
Also I want to show recent twits made by other member .
can you help me
thank you
Hi you’ll have to move the networking code into its own Thread.
Hi Blundell, I have a really strange error, on my app, when the log in screen comes with the permissions requiered by the app, it doesn’t let me put my username or password? any idea what could it be?
H,, are they loading into a webview and it needs to set javascript enabled? Otherwise it’s a browser issue
how can i perform the same task in the tabHost?? when i click on the sing-in button on the web browser it gives the error “android.view.WindowManager$BadTokenException: Unable to add window — token android.app.LocalActivityManager$LocalActivityRecord@40e038c0 is not valid; is your activity running?”
in the tabhost the tweet part it in the child activity.. please help me out..!!
Thanks in advance..!!
Hi sorry I don’t have experience of using a WebView inside of a TabHost, I don’t see an immediate problem. Perhaps try it outside of the tabhost first to ensure you can get it to work with your project, then move it inside.
I’m receiving a weird bug – after logging in and out successfully once using some modified methods from this post, the callback URL twitter sends back is http://api.twitter.commy-callback-url.my-domain.com/etc
Just like that, no space or slash, as if my callback url was directly appended on to the twitter api url.
I’m stumped for ideas, I’d appreciate any help
Hmm that is strange. Maybe try writing a question on StackOverflow with a simple case to reproduce it. I’m sure you’ll get a fair bit of attention
i had the same problem. I fixed it by removing all cookies on logout.
I eventually used this as my logout function:
public void logout() {
Editor editor = mPrefs.edit();
editor.remove(PREF_ACCESS_TOKEN);
editor.commit();
mTwitter.setOAuthAccessToken(null);
CookieSyncManager.createInstance(activity);
CookieManager.getInstance().removeAllCookie();
}
why when i finished login it is not direct again to app but direct to callback url so when i finished login direct to webpage url
I could be wrong but I believe this is necessary to stop hackers using XSS (http://en.wikipedia.org/wiki/Cross-site_scripting) exploits to steal user details.
How would you set this up using Async Task? Every time I try and log in, I get a NetworkOnMainThreadException. Is Async the thing to use here? I am having a hard time implementing it into the code though.
Hi Eric,
This tutorial uses a webview so I don’t see what networking you are doing. You must be doing something outside the tut. but yes you shouldn’t do internet calls on your UI thread, use a background thread or an ASyncTask
Well, when I try and run the app on ICS, it force closes because it’s running in the main thread. So I try and use Async Task, but it won’t let me set up the WebView for some reason..
Oh, and the method that is crashing is loginNewUser
ditto to that problem
should take off the main thread for ICS – awesome tutorial blundell! Thanks for being a legend and commenting
what do u mean by take off main thread…i dont get it can you please explain me
Hi, thanks for sharing. I’m trying to adapt this to an app where the Twitter portion is in it’s own Intent/Activity.
As is, I’m getting a VerifyError exception, it seems to be failing (as noted in the article) on the OAuthAccessToken call. I’m not sure exactly how to fix this (kind of a noob here). Obviously I’ll need to do some doctoring on my manifest, but that’s a bit beyond me at the moment.
Here’s what LogCat has to say:
Could you give me any hints or a direction to go with debugging? Thanks again.
Ooo not too sure about this error, make sure your using the same twitter4j.jar that the tutorial uses, ensure it is added to your manifest correctly. It seems it’s something to do with twitter4j itself
Hello Matt,
I am getting the similar error
Could not find method twitter4j.Twitter.getOAuthAccessToken,
How did you solve the problem?
Thanks.
I’ve since heavily modified this example, so I’m not entirely sure, but as I recall, one of my problems was that the twitter4j library was not being used as a library properly.
Go to your project properties -> Java Build Path -> Order and Export tab, and ensure the box next to the twitter4j JAR is checked.
Your code works (Thanks btw) but when I get to the twitter login web view it doesn’t display the keyboard when I click. I’m pretty sure it has nothing to do with your stuff but, any suggestions what can it be??
Thanks, well done! Hmm I’ve seen issue’s like this before, if you open it in a webview there are a couple of things you can do with enabling javascript (check stackoverflow), but if it is just opening the browser sorry the keyboard opening will just phone dependant.
Solved! It’s a bug from Android untill version 2.1 I think. In case somebody has the same problem, the solution is this here. Thanks for the tutorial!
http://stackoverflow.com/questions/3460915/webview-textarea-doesnt-pop-up-the-keyboard
@mainder, how you fix the code?
I tried, but still the keyboard doesn’t show up..
can you share your code?
private void loginNewUser() {
try {
Log.i(TAG, “Request App Authentication”);
mReqToken = mTwitter.getOAuthRequestToken(CALLBACK_URL);
Log.i(TAG, “Starting Webview to login to twitter”);
WebView twitterSite = new WebView(this);
twitterSite.requestFocus(View.FOCUS_DOWN);
twitterSite.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
if (!v.hasFocus()) {
v.requestFocus();
}
break;
}
return false;
}
});
twitterSite.loadUrl(mReqToken.getAuthenticationURL());
setContentView(twitterSite);
} catch (TwitterException e) {
Toast.makeText(this, “Twitter Login error, try again later”,
Toast.LENGTH_SHORT).show();
}
}
@minder… thank you very much… it’s working now..
Thanks for this, been trying to write a Android Twitter App and kept getting java.lang.NoClassDefFoundError: twitter4j.TwitterFactory
I compared you code with mine and couldn’t see anything I was doing wrong and i’d imported the twitter4j libraries correctly. I did notice that you were using version 2.2.3-1 and I was using 2.2.5 so I swapped to 2.2.3-1 and found my code was now working ok.
So just wondering if you had come across the same problem given that as far as I can tell 2.2.5 was already out when you wrote this tutorial?
Interesting, no I didn’t come across it, I don’t think 2.2.5 was out when I wrote this but if it was I was just lucky and had the older version downloaded!
Hi blundell..I done as step as you write above.But it also as weeber error : “Twitter Login error, try again later”..I look logcat and display error: 401: authentication credential..:(..Do you know how to fix that error.
You need to ensure the clock on your Emulator/Phone is set to the correct time, to allow Twitter oAuth to work
Correct time is what?I run in my phone
and my device set time as time in my computer.I tried with your tutorial but it alway display 401..I also think cause is not correct time but I don’t know synchronize with twitter time.Do you help me.
I have same problem
ensure your phone clock is correct and in the correct timezone
Thanks for the the code it really helped me a lot. One question, how to share url link besided message and image in one tweet?
Looking at the API I can’t see a way to attach pictures. I assume you just attach the URL (like in the tutorial) and twitter will parse it for an image if it has one.
I have imported your project in eclipse, added the necessary consumer key info and ran the app, but I get an error on the callback. it says that the website is not found for the callback url? I haven’t changed anything else…
You may have missed something, have you added your consumer secret as well, and the callback URL in your manifest matches your class?
i tried running but cant continue to tweet since i cant login into twitter(the part where it needs my authentication). am i the only one here who got this kind of error? please help!
Yes Anthony you are
When people successfully tweet, it tweets at me an I get them all the time! Have you got your intents correctly declared in your manifest?
Blundell,
Thank you for such a nice piece of work. Most of the content I have found online is over complicated without a proper justification.
Keep up the tutorials.
Regards.
Thanks for the tutorial. However in my code in the dealWithTwitterResponse method the uri from the line uri = this.getIntent().getData() turns up null. Any idea why?
Hmm the intent shouldn’t be null really!
I think dealWithTwitterResponse should also handle case where users don’t go forward with login (cancel and return return to app). In this case, the uri returned wont have parameter “oauth_verifier” and the app will crash.
In the authorizeNewUser method at mTwitter.getOAuthAccessToken(mReqToken, oauthVerifier) the app is returning an exception.
mReqToken seems to be null.
Any thoughts on this?
Nevermind, I had ‘Don’t keep activities’ active.
Hello thanks for example. I downloaded your project and tried to run that. I changed only consumer key and secret. but it doesn not work. When i press login, toast appears and says “Twitter Login error, try again later” . What did I do wrong?
Hi Mert,
You’ll have to debug it, does the LogCat throw any exceptions? Did you have internet connection? Did you sign up to twitter correctly? Perhaps post a question on stackoverflow it has a nice Q&A design
03-19 10:01:47.806: I/Blundell.TweetToTwitterActivity(197): Login Pressed
03-19 10:01:47.806: I/Blundell.TweetToTwitterActivity(197): New User
03-19 10:01:47.806: I/Blundell.TweetToTwitterActivity(197): Request App Authentication
03-19 10:01:48.744: D/dalvikvm(197): GC freed 6812 objects / 395744 bytes in 69ms
03-19 10:01:48.844: I/global(197): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
03-19 10:01:48.844: I/NotificationService(52): enqueueToast pkg=com.blundell.tut.ttt callback=android.app.ITransientNotification$Stub$Proxy@44dbca90 duration=0
when i press login , see theese on logcat
There is no error in that Log, is it still not working?
Dear Blundell,
I am getting same, still not working, Please give a way to find out error.
I’ve just saw you get it working and tweet at me on Twitter!
Congratz!
Hi blundell, I am getting the same error as described above.
I used your code, added my consumer key and consumer secret. My callback URL is “” (on the twitter app site and in the code) (not sure if this is an issue).
log cat indicates:
08-31 22:41:06.900: Arrived at onResume
08-31 22:41:11.235: Login Pressed
08-31 22:41:11.240: New User
08-31 22:41:11.240: Request App Authentication
I’m quite new to this and am stumped.
Yes it would probably be better if use used a callback URL that wasn’t blank!
Hi blundell, does this code work for you when connected to a 3G/data connection? This and any other twitter4j examples I’ve tried only work on wifi for some reason :/
Yes it should do I can’t see why not. It must be a device issue, or maybe when you create your APK it’s getting pro-guarded and that is removing the twitter4j jar? (random guess).
“Twitter Login error, try again later”
The login is failing, I’m running the same code you posted, I just changed the CONSUMER_KEY and CONSUMER_SECRET to use my keys. The webview never shows up.
You may have missed some code, as it works for many others. Have you checked your manifest? What else does the LogCat say?
I would like to thank you for the sample code . It was really helpful. I created some addition methods to pass the mTwitter across the application but I am getting error in the setTwitter method. I have no idea why it is giving error. Please sujjest . I have pasted the code here http://pastebin.com/PKJcaSpJ
What is the error your getting? If you could post your question on http://stackoverflow.com and link it here I can help with an answer.