Android Twitter oAuth with Twitter4j (without signpost)

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" />

AndroidBasicOAuth

24 thoughts on “Android Twitter oAuth with Twitter4j (without signpost)”

  1. 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…

    1. 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

      1. 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

          1. 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..

  2. 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)

  3. <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="me.crowleydavid.android.basicoauth"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk android:minSdkVersion="4" />
    
        <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" />
    
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:name=".AndroidBasicOAuthActivity"
                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" >
                    </category>
                </intent-filter>
            </activity>
            <activity android:name="TwitterWebviewActivity" >
            </activity>
             <activity android:name="CheckNetAccess">
                <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter></activity>
        </application>
        
    
    </manifest>
    

    Is my Manifest – at a quick look not declaring something properly in the manifest is probably your problem

    1. 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..:)

  4. 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);
    }

  5. 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.

  6. 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):

    1. 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?

  7. 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?

  8. 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?

  9. 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

  10. in OnResume if mRequestToken == null (incorrect pair of keys, your application crushes in :

    i.putExtra(“URL”, mRequestToken.getAuthenticationURL());

    1. Never seen this – this code is not 100% tested with every interaction that a user could complete. Any output from the crash?

    1. Thanks – that is why I made this post. Every other code sample I saw was incomplete or only worked partially.

Leave a Reply