Basic Code for Twitter oAuth for Android works with any version of Android I have tested it against – will crash if no Internet access but adding a check for this is relevantly simple (wanted to keep the code just about the oAuth process – the core idea and code comes from this blogpost
AndroidBasicOAuthActivity Code
package me.crowleydavid.android.basicoauth; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.auth.AccessToken; import twitter4j.auth.RequestToken; import twitter4j.conf.Configuration; import twitter4j.conf.ConfigurationBuilder; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.preference.PreferenceManager; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class AndroidBasicOAuthActivity extends Activity { private int TWITTER_AUTH; private Twitter mTwitter; private RequestToken mRequestToken; private String accessToken; private String accessTokenSecret; private boolean haveConnectedWifi; private boolean haveConnectedMobile; private double x; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); accessToken = settings.getString( "twitter_access_token", null ); accessTokenSecret = settings.getString( "twitter_access_token_secret", null ); Button tweetB = (Button) findViewById(R.id.tweet_button); tweetB.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub updateStatus(); } }); } private boolean haveNetworkConnection() { haveConnectedWifi = false; haveConnectedMobile = false; ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] netInfo = cm.getAllNetworkInfo(); for (NetworkInfo ni : netInfo) { if (ni.getTypeName().equalsIgnoreCase("WIFI")) if (ni.isConnected()) haveConnectedWifi = true; if (ni.getTypeName().equalsIgnoreCase("MOBILE")) if (ni.isConnected()) haveConnectedMobile = true; } return haveConnectedWifi || haveConnectedMobile; } // private void updateStatusLoggedIn() { // SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); // accessToken = settings.getString( "twitter_access_token", null ); // accessTokenSecret = settings.getString( "twitter_access_token_secret", null ); // // // String s2 = String.valueOf(i); // // Toast.makeText(this, s2, 10000).show(); // ConfigurationBuilder builder = new ConfigurationBuilder(); // builder.setOAuthConsumerKey(Constants.CONSUMER_KEY); // builder.setOAuthConsumerSecret(Constants.CONSUMER_SECRET); // builder.setOAuthAccessToken(accessToken); // builder.setOAuthAccessTokenSecret(accessTokenSecret); // Configuration conf = builder.build(); // Twitter t = new TwitterFactory(conf).getInstance(); // i++; // try { // if(i<10){ // t.updateStatus( "Loggedin" + i); // } // } // catch (TwitterException e) { // e.printStackTrace(); // } // // } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub if (requestCode == TWITTER_AUTH) { if (resultCode == Activity.RESULT_OK) { Toast.makeText(this, "Hey Ho", 300).show(); String oauthVerifier = (String) data.getExtras().get("oauth_verifier"); AccessToken at = null; try { // Pair up our request with the response at = mTwitter.getOAuthAccessToken(oauthVerifier); String theToken = at.getToken(); // Toast.makeText(this, theToken, 10000).show(); String theTokenSecret = at.getTokenSecret(); // Toast.makeText(this, theTokenSecret, 10000).show(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); settings = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = settings.edit(); editor.putString("twitter_access_token",theToken); editor.putString("twitter_access_token_secret", theTokenSecret); editor.commit(); // his method // settings.edit() // .putString( "twitter_access_token", at.getToken() ) // .putString( "twitter_access_token_secret", at.getTokenSecret() ) // .commit(); // Intent i = new Intent(this, someclass.class); // startActivity(i); updateStatus(); } catch (TwitterException e) { e.printStackTrace(); } } } else { Toast.makeText(this, "uh oh, Spaghetti Os", 300).show(); } } private void updateStatus() { // TODO Auto-generated method stub SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); accessToken = settings.getString( "twitter_access_token", null ); accessTokenSecret = settings.getString( "twitter_access_token_secret", null ); // Toast.makeText(this, accessToken, 10000).show(); // Toast.makeText(this, accessTokenSecret, 10000).show(); haveNetworkConnection(); if ((haveConnectedWifi)|| (haveConnectedMobile)){ ConfigurationBuilder builder = new ConfigurationBuilder(); builder.setOAuthConsumerKey(Constants.CONSUMER_KEY); builder.setOAuthConsumerSecret(Constants.CONSUMER_SECRET); builder.setOAuthAccessToken(accessToken); builder.setOAuthAccessTokenSecret(accessTokenSecret); Configuration conf = builder.build(); Twitter t = new TwitterFactory(conf).getInstance(); try { x = Math.random(); t.updateStatus( "Yo ho ho and a bottle of rum " + x); } catch (TwitterException e) { e.printStackTrace(); } } else{ Toast.makeText(this, "No access to Internet..please try again", 3000).show(); } } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); accessToken = settings.getString( "twitter_access_token", null ); accessTokenSecret = settings.getString( "twitter_access_token_secret", null ); haveNetworkConnection(); if ((haveConnectedWifi)|| (haveConnectedMobile)){ // Toast.makeText(this, "Internet is go!", 3000).show(); // Intent i = new Intent(this, AndroidBasicOAuthActivity.class); // startActivity(i); if ((accessToken==null)||(accessTokenSecret==null)){ mTwitter = new TwitterFactory().getInstance(); mRequestToken = null; mTwitter.setOAuthConsumer(Constants.CONSUMER_KEY,Constants.CONSUMER_SECRET ); String callbackURL = getResources().getString(R.string.twitter_callback); try { mRequestToken = mTwitter.getOAuthRequestToken(callbackURL); } catch (TwitterException e) { e.printStackTrace(); } Intent i = new Intent(this, TwitterWebviewActivity.class); i.putExtra("URL", mRequestToken.getAuthenticationURL()); startActivityForResult(i, TWITTER_AUTH); } else{ Toast.makeText(this, "Token found..logged in", 3000).show(); // updateStatusLoggedIn(); } } else{ Toast.makeText(this, "No access to Internet..please try again", 3000).show(); Intent i = new Intent(this, CheckNetAccess.class); startActivity(i); } } }
Constants Code you need to enter your own Twitter Developer keys here
package me.crowleydavid.android.basicoauth; public class Constants { public static final String CONSUMER_KEY = "************"; public static final String CONSUMER_SECRET= "**************";
TwitterWebviewActivity Code
package me.crowleydavid.android.basicoauth; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.webkit.WebView; import android.webkit.WebViewClient; public class TwitterWebviewActivity extends Activity { private Intent mIntent; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.twitter_webview); mIntent = getIntent(); String url = (String)mIntent.getExtras().get("URL"); WebView webView = (WebView) findViewById(R.id.webview); webView.setWebViewClient( new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if( url.contains(getResources().getString( R.string.twitter_callback ))) { Uri uri = Uri.parse( url ); String oauthVerifier = uri.getQueryParameter( "oauth_verifier" ); mIntent.putExtra( "oauth_verifier", oauthVerifier ); setResult( RESULT_OK, mIntent ); finish(); return true; } return false; } }); webView.loadUrl(url); } }
}
CheckNetAccess Code
package me.crowleydavid.android.basicoauth; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class CheckNetAccess extends Activity { private boolean haveConnectedWifi; private boolean haveConnectedMobile; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.checknet); Button netB = (Button) findViewById(R.id.netbutton); netB.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub haveNetworkConnection(); if ((haveConnectedWifi)|| (haveConnectedMobile)){ Toast.makeText(CheckNetAccess.this, "Internet is go!", 3000).show(); Intent i = new Intent(CheckNetAccess.this, AndroidBasicOAuthActivity.class); startActivity(i); } else{ Toast.makeText(CheckNetAccess.this, "No access to Internet..please try again", 3000).show(); } } }); } private boolean haveNetworkConnection() { haveConnectedWifi = false; haveConnectedMobile = false; ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] netInfo = cm.getAllNetworkInfo(); for (NetworkInfo ni : netInfo) { if (ni.getTypeName().equalsIgnoreCase("WIFI")) if (ni.isConnected()) haveConnectedWifi = true; if (ni.getTypeName().equalsIgnoreCase("MOBILE")) if (ni.isConnected()) haveConnectedMobile = true; } return haveConnectedWifi || haveConnectedMobile; } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); } }
Android Manifest needs these permissions
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
i have tried your tutorial but when i run on android it says “unfortunately your activity has stopped”..i don’t know what is the problem…
Hi,
I have updated the code and uploaded a newer version that checks for net connection and fixed a bug i found. Hopefully this will fix your problem!
David
hi…thank you…
but i still have the same problem, there is no error but it always says unfortunately has stopped. i don’t what is the real problem here..
by the way i use is new version can influent the whole structure??…
obvioulsy im just newbie..:)
thank you david..
christian
uses-sdk android:minSdkVersion=”15
Have you entered in your two Twitter keys into the Constants.java?
yes…i’ve entered the consumer key and consumer secret…
how about the callback url?..what should i put on callback url?
anyway sorry for disturbing your time..but i need your help, thank you..
here is the error on logcat:
java.lang.VerifyError: com/example/Twitterandroid
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1319)
at android.app.Instrumentation.newActivity(Instrumentation.java:1023)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1871)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Is my Manifest – at a quick look not declaring something properly in the manifest is probably your problem
thank you, my problem has solved…when i use android:minSdkVersion=”7″ it can start normally..:)
but how can i see the timeline??..do i have to create unauthenticatedTwitter.getPublicTimeline()??
btw thank you very much..:)
You can try something like this – this just prints them out to logcat in Eclipse
try {
TwitterFactory factory = new TwitterFactory(cb.build());
// gets Twitter instance with default credentials
Twitter twitter = factory.getInstance();
User user = twitter.verifyCredentials();
List statuses = twitter.getHomeTimeline();
System.out.println(“Showing @” + user.getScreenName() + “‘s home timeline.”);
for (Status status : statuses) {
System.out.println(“@” + status.getUser().getScreenName() + ” – ” + status.getText() + “–“+status.getURLEntities()+ “–“+status.getURLEntities());
// Log.v(“Logged”, “@” + status.getUser().getScreenName() + ” – ” + status.getText() + “–“+status.getURLEntities()+ “–“+status.getURLEntities());
}
} catch (TwitterException te) {
te.printStackTrace();
System.out.println(“Failed to get timeline: ” + te.getMessage());
System.exit(-1);
}
please tell me how to get recents tweets in simple way
Thanx a lot of for this tutorial .
Had been searching for something like this for a while. Are there any other libraries other than twitter4j with which this can be implemented.
There is other https://dev.twitter.com/docs/twitter-libraries#java but not sure of compatibility with Android and how well they are maintained
getting the following error if i mentioned any callback URL..
401:Authentication credentials (http://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid conumer key/secret, access token/secret, and the system clock in in sync.
12-03 10:45:09.772: W/System.err(859):
12-03 10:45:09.772: W/System.err(859):
12-03 10:45:09.772: W/System.err(859): /oauth/request_token
12-03 10:45:09.772: W/System.err(859): Desktop applications only support the oauth_callback value ‘oob’
12-03 10:45:09.772: W/System.err(859):
Make sure you do have the correct system time – if you have the wrong system time your API request will be rejected. And make sure your keys are correct?
I tried your code and I got to the Authorized your app web view with “sign in” and “cancel” button. I pressed the “sign in” button but nothing happens. If I pressed the “cancel button” I got back into the code at shouldOverrideUrlLoading(…). But the “sign in” button does nothing and I am stuck on this screen. Do you know why?
No idea – I have never seen that problem. Does it happen on all devices/emulators?
I build an app based on your tutorial here, but i’m facing an error if i choose cancel in twitter oauth page. I think it’s because the result code. Any idea?
In this code I haven’t implemented anything for that – I’ll have to look into it
What should I put in the call back URL? I’m having a really hard time facing this problem
I’d like to return main activity after the user allowed access to twitter
in OnResume if mRequestToken == null (incorrect pair of keys, your application crushes in :
i.putExtra(“URL”, mRequestToken.getAuthenticationURL());
Never seen this – this code is not 100% tested with every interaction that a user could complete. Any output from the crash?
Awesome, the only one that actually works! Just awesome
Thanks – that is why I made this post. Every other code sample I saw was incomplete or only worked partially.