Android Twitter integration using oauth and twitter4j
Asked Answered
T

5

17

I want to integrate twitter in an android application and found many tutorials. Implemented 2 of them. But after implementing, when ran the application, I came to know that they use older version of twitter4J library.

Although plenty other tutorials are available but none of them is latest one.i.e. just 2-3 months older. I need a tutorial or example which uses latest twitter4J library version which is twitter4j-core-3.0.3.

My main aim is to allow user to post tweets on his/her account. But again, if user is not logged in then, I first need to ask for credentials. Also, if user clicks on logout button then I need some way to log the user out.

Tomasatomasina answered 6/7, 2013 at 5:18 Comment(4)
Twitter uses OAuth 1.0AFant
@Fant Thanks for letting me know this. I'll edit my question accordingly.Tomasatomasina
follow this tutorial tech-papers.org/integrate-twitter-with-android-applicationJamilajamill
the link appears to be broken Mr VickyTiffie
T
29

I solved the problem. I made changes to the code I found in a tutorial to make it work. Copying the whole code here. Just replace with your ConsumerKey and ConsumerSecret.

You need to add twitter4j library to your project's libs folder.

AndroidManifest.xml :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidhive.twitterconnect"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />

    <!-- 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=".MainActivity"
            android:label="@string/title_activity_main" >
            <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>
    </application>

</manifest>

MainActivity.java :

package com.androidhive.twitterconnect;

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 com.androidhive.twitterconnect.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    // Constants
    /**
     * Register your here app https://dev.twitter.com/apps/new and get your
     * consumer key and secret
     * */
    static String TWITTER_CONSUMER_KEY = "PutYourConsumerKeyHere"; // place your cosumer key here
    static String TWITTER_CONSUMER_SECRET = "PutYourConsumerSecretHere"; // place your consumer secret here

    // Preference Constants
    static String PREFERENCE_NAME = "twitter_oauth";
    static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
    static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret";
    static final String PREF_KEY_TWITTER_LOGIN = "isTwitterLogedIn";

    static final String TWITTER_CALLBACK_URL = "oauth://t4jsample";

    // Twitter oauth urls
    static final String URL_TWITTER_AUTH = "auth_url";
    static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
    static final String URL_TWITTER_OAUTH_TOKEN = "oauth_token";

    // Login button
    Button btnLoginTwitter;
    // Update status button
    Button btnUpdateStatus;
    // Logout button
    Button btnLogoutTwitter;
    // EditText for update
    EditText txtUpdate;
    // lbl update
    TextView lblUpdate;
    TextView lblUserName;

    // Progress dialog
    ProgressDialog pDialog;

    // Twitter
    private static Twitter twitter;
    private static RequestToken requestToken;
    private AccessToken accessToken;

    // Shared Preferences
    private static SharedPreferences mSharedPreferences;

    // Internet Connection detector
    private ConnectionDetector cd;

    // Alert Dialog Manager
    AlertDialogManager alert = new AlertDialogManager();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        cd = new ConnectionDetector(getApplicationContext());

        // Check if Internet present
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(MainActivity.this, "Internet Connection Error",
                    "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }

        // Check if twitter keys are set
        if(TWITTER_CONSUMER_KEY.trim().length() == 0 || TWITTER_CONSUMER_SECRET.trim().length() == 0){
            // Internet Connection is not present
            alert.showAlertDialog(MainActivity.this, "Twitter oAuth tokens", "Please set your twitter oauth tokens first!", false);
            // stop executing code by return
            return;
        }

        // All UI elements
        btnLoginTwitter = (Button) findViewById(R.id.btnLoginTwitter);
        btnUpdateStatus = (Button) findViewById(R.id.btnUpdateStatus);
        btnLogoutTwitter = (Button) findViewById(R.id.btnLogoutTwitter);
        txtUpdate = (EditText) findViewById(R.id.txtUpdateStatus);
        lblUpdate = (TextView) findViewById(R.id.lblUpdate);
        lblUserName = (TextView) findViewById(R.id.lblUserName);

        // Shared Preferences
        mSharedPreferences = getApplicationContext().getSharedPreferences(
                "MyPref", 0);

        /**
         * Twitter login button click event will call loginToTwitter() function
         * */
        btnLoginTwitter.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Call login twitter function
                loginToTwitter();
            }
        });

        /**
         * Button click event to Update Status, will call updateTwitterStatus()
         * function
         * */
        btnUpdateStatus.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Call update status function
                // Get the status from EditText
                String status = txtUpdate.getText().toString();

                // Check for blank text
                if (status.trim().length() > 0) {
                    // update status
                    new updateTwitterStatus().execute(status);
                } else {
                    // EditText is empty
                    Toast.makeText(getApplicationContext(),
                            "Please enter status message", Toast.LENGTH_SHORT)
                            .show();
                }
            }
        });

        /**
         * Button click event for logout from twitter
         * */
        btnLogoutTwitter.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Call logout twitter function
                logoutFromTwitter();
            }
        });

        /** This if conditions is tested once is
         * redirected from twitter page. Parse the uri to get oAuth
         * Verifier
         * */
        if (!isTwitterLoggedInAlready()) {
            Uri uri = getIntent().getData();
            if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
                // oAuth verifier
                final String verifier = uri
                        .getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);

                try {

                    Thread thread = new Thread(new Runnable(){
                        @Override
                        public void run() {
                            try {

                                // Get the access token
                                MainActivity.this.accessToken = twitter.getOAuthAccessToken(
                                        requestToken, verifier);

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                    thread.start();

                    // Shared Preferences
                    Editor e = mSharedPreferences.edit();

                    // After getting access token, access token secret
                    // store them in application preferences
                    e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                    e.putString(PREF_KEY_OAUTH_SECRET,
                            accessToken.getTokenSecret());
                    // Store login status - true
                    e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                    e.commit(); // save changes

                    Log.e("Twitter OAuth Token", "> " + accessToken.getToken());

                    // Hide login button
                    btnLoginTwitter.setVisibility(View.GONE);

                    // Show Update Twitter
                    lblUpdate.setVisibility(View.VISIBLE);
                    txtUpdate.setVisibility(View.VISIBLE);
                    btnUpdateStatus.setVisibility(View.VISIBLE);
                    btnLogoutTwitter.setVisibility(View.VISIBLE);

                    // Getting user details from twitter
                    // For now i am getting his name only
                    long userID = accessToken.getUserId();
                    User user = twitter.showUser(userID);
                    String username = user.getName();

                    // Displaying in xml ui
                    lblUserName.setText(Html.fromHtml("<b>Welcome " + username + "</b>"));
                } catch (Exception e) {
                    // Check log for login errors
                    Log.e("Twitter Login Error", "> " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * Function to login twitter
     * */
    private void loginToTwitter() {
        // Check if already logged in
        if (!isTwitterLoggedInAlready()) {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
            builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
            Configuration configuration = builder.build();

            TwitterFactory factory = new TwitterFactory(configuration);
            twitter = factory.getInstance();


                Thread thread = new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {

                            requestToken = twitter
                                    .getOAuthRequestToken(TWITTER_CALLBACK_URL);
                            MainActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
                                    .parse(requestToken.getAuthenticationURL())));

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                thread.start();         
        } else {
            // user already logged into twitter
            Toast.makeText(getApplicationContext(),
                    "Already Logged into twitter", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Function to update status
     * */
    class updateTwitterStatus extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Updating to twitter...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * getting Places JSON
         * */
        protected String doInBackground(String... args) {
            Log.d("Tweet Text", "> " + args[0]);
            String status = args[0];
            try {
                ConfigurationBuilder builder = new ConfigurationBuilder();
                builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
                builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);

                // 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
                twitter4j.Status response = twitter.updateStatus(status);

                Log.d("Status", "> " + response.getText());
            } catch (TwitterException e) {
                // Error in updating status
                Log.d("Twitter Update Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog and show
         * the data in UI Always use runOnUiThread(new Runnable()) to update UI
         * from background thread, otherwise you will get error
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog after getting all products
            pDialog.dismiss();
            // updating UI from Background Thread
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(),
                            "Status tweeted successfully", Toast.LENGTH_SHORT)
                            .show();
                    // Clearing EditText field
                    txtUpdate.setText("");
                }
            });
        }

    }

    /**
     * Function to logout from twitter
     * It will just clear the application shared preferences
     * */
    private void logoutFromTwitter() {
        // Clear the shared preferences
        Editor e = mSharedPreferences.edit();
        e.remove(PREF_KEY_OAUTH_TOKEN);
        e.remove(PREF_KEY_OAUTH_SECRET);
        e.remove(PREF_KEY_TWITTER_LOGIN);
        e.commit();

        // After this take the appropriate action
        // I am showing the hiding/showing buttons again
        // You might not needed this code
        btnLogoutTwitter.setVisibility(View.GONE);
        btnUpdateStatus.setVisibility(View.GONE);
        txtUpdate.setVisibility(View.GONE);
        lblUpdate.setVisibility(View.GONE);
        lblUserName.setText("");
        lblUserName.setVisibility(View.GONE);

        btnLoginTwitter.setVisibility(View.VISIBLE);
    }

    /**
     * Check user already logged in your application using twitter Login flag is
     * fetched from Shared Preferences
     * */
    private boolean isTwitterLoggedInAlready() {
        // return twitter login status from Shared Preferences
        return mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
    }

    protected void onResume() {
        super.onResume();
    }

}

AlertDialogManager.java :

package com.androidhive.twitterconnect;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;

public class AlertDialogManager {
    /**
     * Function to display simple Alert Dialog
     * @param context - application context
     * @param title - alert dialog title
     * @param message - alert message
     * @param status - success/failure (used to set icon)
     *               - pass null if you don't want icon
     * */
    public void showAlertDialog(Context context, String title, String message,
        Boolean status) {
        AlertDialog alertDialog = new AlertDialog.Builder(context).create();

        // Setting Dialog Title
        alertDialog.setTitle(title);

        // Setting Dialog Message
            alertDialog.setMessage(message);

        if(status != null)
            // Setting alert dialog icon
            alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);

        // Setting OK Button
        alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }
}

ConnectionDetector.java :

package com.androidhive.twitterconnect;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class ConnectionDetector {

    private Context _context;

    public ConnectionDetector(Context context){
        this._context = context;
    }

    /**
     * Checking for all possible internet providers
     * **/
    public boolean isConnectingToInternet(){
        ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
          if (connectivity != null)
          {
              NetworkInfo[] info = connectivity.getAllNetworkInfo();
              if (info != null)
                  for (int i = 0; i < info.length; i++)
                      if (info[i].getState() == NetworkInfo.State.CONNECTED)
                      {
                          return true;
                      }

          }
          return false;
    }
}

This is original code by Ravi Tamada. The changes I made are in MainActivity.java and AndroidManifest.xml files only.

Tomasatomasina answered 6/7, 2013 at 9:47 Comment(13)
Hello @akash r u solved ur problem ? i m used twitter4j 2.3.5 library that contain method to send tweet another user. if u not still solved ur problem then reply. sorry for late response Thanks.Sverige
i tried this code the access token is returning null plz helpPerren
@Perren Make sure you have created access token at dev.twitter.com. If you have already then try removing them and recreate. Also check that your consumer key and consumer secret are set.Tomasatomasina
actually i solved the problem it was because of the above code sequence , the access token is fetched in a seperate thread and it was persisted to the shared preference in the main thread and since code from the seperate thread would run after or before the code in main thread is not fixed , in my case the code in main thread was running before it was fetching the access token and thats why it was null , so i changed it to asynctask .. but thanx anywaysPerren
@Perren AsyncTask also runs on a separate thread. Then it made difference. Just curious to know.Tomasatomasina
@Akash ya because then we can put the code which uses the access token in onPostExecute(which runs on main thread) and be sure that when we persist access token we actually have instead of taking a chance with dvm.Perren
So everyone knows, I got it to work as Ravi did: by calling twitter.getOAuthAccessToken(requestToken, verifier); in an AsyncTask. Otherwise it retrieves the token only after onCreate() is finished.Scotney
@Perren can u plzz provide an working example for this i am trying to get it right but no luck plzz help me out hereHinz
@MilanPalSingh i have posted an answer with my working example . But this is just an example it does not check for internet connection and other things but it will straightPerren
Ravi Tamada code is not working ! See the discussion in Comments about the error ! And i m getting this error 01-26 13:02:25.839: E/Twitter Login Error(2022): > null 01-26 13:02:25.839: W/System.err(2022): java.lang.NullPointerException 01-26 13:02:25.839: W/System.err(2022): at com.androidhive.twitterconnect.MainActivity.onCreate(MainActivity.java:200) 01-26 13:02:25.839: W/System.err(2022): at android.app.Activity.performCreate(Activity.java:5243) 01-26 13:02:25.839: W/System.err(2022): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)Manella
But my biggest problem is that twitter page should be shown inside a WebView owned by the application otherwise you run into lifecycle issues and user has browser windows left on the stack with expired oauth pages, not goodTolbert
Sorry, but I'm thinking about keeping CONSUMER and SECRET keys here in plain text. Someone could easily decompile the app and get these 2 Strings. What could him do with these? Is it dangerous to have them here in plain text?Preciado
@Tomasatomasina I tried your code with 4.0.7 version twitter4j but I don't see dialog button when I click Login with Twitter . Please helpSundaysundberg
R
9

I found a good example which works well with twitter4j 3.0.3 on android. Others do not work. http://hintdesk.com/how-to-tweet-in-twitter-within-android-client/

Retina answered 2/9, 2013 at 16:8 Comment(2)
A link is not an answer. And that link does not even provide complete code. If you were able to get this to work please post code.Assort
@rcompton That link is a complete tutorial. It is not necessary to copy and paste all contents here. It does not provide a complete project, but it does provide the core code. Everyone who has learned Android programming for several days should understand it. I googled and tried many examples but all of them do not work well. Maybe that’s because twitter changed api to oauth v1.1 and these examples are not updated. This example is the only one that works with twitter4j 3.0.3 on android.Retina
P
4

This is the working example from my code , i am using twitter4j and also you don't need to set any intent in manifest since i use webview instead of browser.

Place your consumer and secret key and you should be good to go

package com.example.mysituationtwittertest;

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.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
// Constants
/**
 * Register your here app https://dev.twitter.com/apps/new and get your
 * consumer key and secret
 * */
static String TWITTER_CONSUMER_KEY = "XXXXXXXXXXXXXXXXXXX"; // place your
                                                                // cosumer
                                                                // key here
static String TWITTER_CONSUMER_SECRET = "XXXXXXXXXXXXXXXX"; // place
                                                                                    // your
                                                                                    // consumer
                                                                                    // secret
                                                                                    // here

// Preference Constants
static String PREFERENCE_NAME = "twitter_oauth";
static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret";
static final String PREF_KEY_TWITTER_LOGIN = "isTwitterLogedIn";

static final String TWITTER_CALLBACK_URL = "oauth://youdare";

// Twitter oauth urls
static final String URL_TWITTER_AUTH = "auth_url";
static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
static final String URL_TWITTER_OAUTH_TOKEN = "oauth_token";

// Login button
Button btnShareTwitter;

WebView myWebView;

// Twitter
private static Twitter twitter;
private static RequestToken requestToken;
private AccessToken accessToken;

// Shared Preferences
private static SharedPreferences mSharedPreferences;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // All UI elements
    btnShareTwitter = (Button) findViewById(R.id.btnShareTwitter);
    myWebView = (WebView) findViewById(R.id.webView1);

    myWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
            if (url != null && url.startsWith(TWITTER_CALLBACK_URL))
                new AfterLoginTask().execute(url);
            else
                webView.loadUrl(url);
            return true;
        }
    });

    // Shared Preferences
    mSharedPreferences = getApplicationContext().getSharedPreferences(
            "MyPref", 0);

    /**
     * Twitter login button click event will call loginToTwitter() function
     * */
    btnShareTwitter.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Call login twitter function
            new LoginTask().execute();
        }
    });

}

/**
 * Function to login twitter
 * */
private void loginToTwitter() {
    // Check if already logged in
    if (!isTwitterLoggedInAlready()) {
        ConfigurationBuilder builder = new ConfigurationBuilder();
        builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
        builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
        Configuration configuration = builder.build();

        TwitterFactory factory = new TwitterFactory(configuration);
        twitter = factory.getInstance();

        try {
            requestToken = twitter
                    .getOAuthRequestToken(TWITTER_CALLBACK_URL);
        } catch (TwitterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    else {
        // user already logged into twitter
        Toast.makeText(getApplicationContext(),
                "Already Logged into twitter", Toast.LENGTH_LONG).show();
    }
}

/**
 * Check user already logged in your application using twitter Login flag is
 * fetched from Shared Preferences
 * */
private boolean isTwitterLoggedInAlready() {
    // return twitter login status from Shared Preferences
    return mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
}

public void handleTwitterCallback(String url) {

    Uri uri = Uri.parse(url);

    // oAuth verifier
    final String verifier = uri
            .getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);

    try {

        // Get the access token
        MainActivity.this.accessToken = twitter.getOAuthAccessToken(
                requestToken, verifier);

        // Shared Preferences
        Editor e = mSharedPreferences.edit();

        // After getting access token, access token secret
        // store them in application preferences
        e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
        e.putString(PREF_KEY_OAUTH_SECRET, accessToken.getTokenSecret());
        // Store login status - true
        e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
        e.commit(); // save changes

        Log.e("Twitter OAuth Token", "> " + accessToken.getToken());

        ConfigurationBuilder builder = new ConfigurationBuilder();
        builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
        builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);

        // 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
        twitter4j.Status response = twitter
                .updateStatus("XXXXXXXXXXXXXXXXX");

    } catch (Exception e) {
        e.printStackTrace();
    }
}

class LoginTask extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected Boolean doInBackground(Void... params) {
        // TODO Auto-generated method stub
        loginToTwitter();
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub

        myWebView.loadUrl(requestToken.getAuthenticationURL());
        myWebView.setVisibility(View.VISIBLE);
        myWebView.requestFocus(View.FOCUS_DOWN);

    }

}

class AfterLoginTask extends AsyncTask<String, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        myWebView.clearHistory();
    }

    @Override
    protected Boolean doInBackground(String... params) {
        // TODO Auto-generated method stub
        handleTwitterCallback(params[0]);
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        myWebView.setVisibility(View.GONE);
        Toast.makeText(MainActivity.this, "Tweet Successful",
                Toast.LENGTH_SHORT).show();

    }

}

@Override
public void onBackPressed() {
    if (myWebView.getVisibility() == View.VISIBLE) {
        if (myWebView.canGoBack()) {
            myWebView.goBack();
            return;
        } else {
            myWebView.setVisibility(View.GONE);
            return;
        }
    }
    super.onBackPressed();
}

}
Perren answered 24/1, 2014 at 5:57 Comment(2)
Do you face same issue as this #24205355?Tomasatomasina
No i havent faced this issue and after login i close my webview so i don't there would be this issue with this flow.Perren
S
3

To illustrate my comment above, here is my final working MainActivity class. Pretty similar to the code above, the differences are :

  • the internal class OAuthAccessTokenTask, that includes the retrieval of the Oauth token and the user information
  • its callback onRequestTokenRetrieved(Exception)

Also, note that to get this to work you must declare a callback url on your twitter app settings, even a phony one. It took me a few hours to figure out the way it works.

When you check the twitter4j documentation, the first pieces of code refer to a PIN code you have to get from an authorisation webpage. That's what happens when no callback url is set in your app. It's called PIN based authentication and you don't want to use it on a mobile :)

public class MainActivity extends Activity {
    // Constants
    /**
     * Register your here app https://dev.twitter.com/apps/new and get your
     * consumer key and secret
     * */
    static String TWITTER_CONSUMER_KEY = "PutYourConsumerKeyHere"; // place your cosumer key here
    static String TWITTER_CONSUMER_SECRET = "PutYourConsumerSecretHere"; // place your consumer secret here

    // Preference Constants
    static String PREFERENCE_NAME = "twitter_oauth";
    static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
    static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret";
    static final String PREF_KEY_TWITTER_LOGIN = "isTwitterLogedIn";

    static final String TWITTER_CALLBACK_URL = "oauth://t4jsample";

    // Twitter oauth urls
    static final String URL_TWITTER_AUTH = "auth_url";
    static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
    static final String URL_TWITTER_OAUTH_TOKEN = "oauth_token";

    // Login button
    Button btnLoginTwitter;
    // Update status button
    Button btnUpdateStatus;
    // Logout button
    Button btnLogoutTwitter;
    // EditText for update
    EditText txtUpdate;
    // lbl update
    TextView lblUpdate;
    TextView lblUserName;

    // Progress dialog
    ProgressDialog pDialog;

    // Twitter
    private static Twitter twitter;
    private static RequestToken requestToken;
    private AccessToken accessToken;
    private User user;

    // Shared Preferences
    private static SharedPreferences mSharedPreferences;

    // Internet Connection detector
    private ConnectionDetector cd;

    // Alert Dialog Manager
    AlertDialogManager alert = new AlertDialogManager();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        cd = new ConnectionDetector(getApplicationContext());

        // Check if Internet present
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(MainActivity.this, "Internet Connection Error", "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }

        // Check if twitter keys are set
        if(TWITTER_CONSUMER_KEY.trim().length() == 0 || TWITTER_CONSUMER_SECRET.trim().length() == 0){
            // Internet Connection is not present
            alert.showAlertDialog(MainActivity.this, "Twitter oAuth tokens", "Please set your twitter oauth tokens first!", false);
            // stop executing code by return
            return;
        }

        // All UI elements
        btnLoginTwitter = (Button) findViewById(R.id.btnLoginTwitter);
        btnUpdateStatus = (Button) findViewById(R.id.btnUpdateStatus);
        btnLogoutTwitter = (Button) findViewById(R.id.btnLogoutTwitter);
        txtUpdate = (EditText) findViewById(R.id.txtUpdateStatus);
        lblUpdate = (TextView) findViewById(R.id.lblUpdate);
        lblUserName = (TextView) findViewById(R.id.lblUserName);

        // Shared Preferences
        mSharedPreferences = getApplicationContext().getSharedPreferences("MyPref", 0);

        /**
         * Twitter login button click event will call loginToTwitter() function
         * */
        btnLoginTwitter.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Call login twitter function
                loginToTwitter();
            }
        });

        /**
         * Button click event to Update Status, will call updateTwitterStatus()
         * function
         * */
        btnUpdateStatus.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Call update status function
                // Get the status from EditText
                String status = txtUpdate.getText().toString();

                // Check for blank text
                if (status.trim().length() > 0) {
                    // update status
                    new updateTwitterStatus().execute(status);
                } else {
                    // EditText is empty
                    Toast.makeText(
                            getApplicationContext(),
                            "Please enter status message", 
                            Toast.LENGTH_SHORT
                    ).show();
                }
            }
        });

        /**
         * Button click event for logout from twitter
         * */
        btnLogoutTwitter.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Call logout twitter function
                logoutFromTwitter();
            }
        });

        /** This if conditions is tested once is
         * redirected from twitter page. Parse the uri to get oAuth
         * Verifier
         * */
        if (!isTwitterLoggedInAlready()) {
            Uri uri = getIntent().getData();
            if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {

                // oAuth verifier
                String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
                new OAuthAccessTokenTask().execute(verifier);
            }
        }

    }

     private class OAuthAccessTokenTask extends AsyncTask<String, Void, Exception>
     {
        @Override
        protected Exception doInBackground(String... params) {
            Exception toReturn = null;

            try {
                accessToken = twitter.getOAuthAccessToken(requestToken, params[0]);
                user = twitter.showUser(accessToken.getUserId());

            }
            catch(TwitterException e) {
                Log.e(MainActivity.class.getName(), "TwitterError: " + e.getErrorMessage());
                toReturn = e;
            }
            catch(Exception e) {
                Log.e(MainActivity.class.getName(), "Error: " + e.getMessage());
                toReturn = e;
            }

            return toReturn;
        }

        @Override
        protected void onPostExecute(Exception exception) {
            onRequestTokenRetrieved(exception);
        }
     }

     private void onRequestTokenRetrieved(Exception result) {

         if (result != null) {
             Toast.makeText(
                     this, 
                     result.getMessage(), 
                     Toast.LENGTH_LONG
                     ).show();
         }

         else {
             try {
                 // Shared Preferences
                 Editor editor = mSharedPreferences.edit();

                 // After getting access token, access token secret
                 // store them in application preferences
                 editor.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                 editor.putString(PREF_KEY_OAUTH_SECRET,
                         accessToken.getTokenSecret());
                 // Store login status - true
                 editor.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                 editor.commit(); // save changes

                 Log.e("Twitter OAuth Token", "> " + accessToken.getToken());

                 // Hide login button
                 btnLoginTwitter.setVisibility(View.GONE);

                 // Show Update Twitter
                 lblUpdate.setVisibility(View.VISIBLE);
                 txtUpdate.setVisibility(View.VISIBLE);
                 btnUpdateStatus.setVisibility(View.VISIBLE);
                 btnLogoutTwitter.setVisibility(View.VISIBLE);

                 // Getting user details from twitter
                 String username = user.getName();

                 // Displaying in xml ui
                 lblUserName.setText(Html.fromHtml("<b>Welcome " + username + "</b>"));
             }
             catch (Exception ex) {
                 // Check log for login errors
                 Log.e("Twitter Login Error", "> " + ex.getMessage());
                 ex.printStackTrace();
             }
         }
     }

    /**
     * Function to login twitter
     * */
    private void loginToTwitter() {
        // Check if already logged in
        if (!isTwitterLoggedInAlready()) {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
            builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
            Configuration configuration = builder.build();

            TwitterFactory factory = new TwitterFactory(configuration);
            twitter = factory.getInstance();


                Thread thread = new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {
                            requestToken = twitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
                            MainActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())));

                        } catch (Exception e) {
                            e.printStackTrace();
                            Toast.makeText(getApplicationContext(), "Already Logged into twitter", Toast.LENGTH_LONG).show();
                        }
                    }
                });
                thread.start();         
        } else {
            // user already logged into twitter
            Toast.makeText(getApplicationContext(), "Already Logged into twitter", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Function to update status
     * */
    class updateTwitterStatus extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Updating to twitter...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * getting Places JSON
         * */
        protected String doInBackground(String... args) {
            Log.d("Tweet Text", "> " + args[0]);
            String status = args[0];
            try {
                ConfigurationBuilder builder = new ConfigurationBuilder();
                builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
                builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);

                // 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
                twitter4j.Status response = twitter.updateStatus(status);

                Log.d("Status", "> " + response.getText());
            } catch (TwitterException e) {
                // Error in updating status
                Log.d("Twitter Update Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog and show
         * the data in UI Always use runOnUiThread(new Runnable()) to update UI
         * from background thread, otherwise you will get error
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog after getting all products
            pDialog.dismiss();
            // updating UI from Background Thread
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(),
                            "Status tweeted successfully", Toast.LENGTH_SHORT)
                            .show();
                    // Clearing EditText field
                    txtUpdate.setText("");
                }
            });
        }
    }

    /**
     * Function to logout from twitter
     * It will just clear the application shared preferences
     * */
    private void logoutFromTwitter() {
        // Clear the shared preferences
        Editor e = mSharedPreferences.edit();
        e.remove(PREF_KEY_OAUTH_TOKEN);
        e.remove(PREF_KEY_OAUTH_SECRET);
        e.remove(PREF_KEY_TWITTER_LOGIN);
        e.commit();

        // After this take the appropriate action
        // I am showing the hiding/showing buttons again
        // You might not needed this code
        btnLogoutTwitter.setVisibility(View.GONE);
        btnUpdateStatus.setVisibility(View.GONE);
        txtUpdate.setVisibility(View.GONE);
        lblUpdate.setVisibility(View.GONE);
        lblUserName.setText("");
        lblUserName.setVisibility(View.GONE);

        btnLoginTwitter.setVisibility(View.VISIBLE);
    }

    /**
     * Check user already logged in your application using twitter Login flag is
     * fetched from Shared Preferences
     * */
    private boolean isTwitterLoggedInAlready() {
        // return twitter login status from Shared Preferences
        return mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
    }

    protected void onResume() {
        super.onResume();
    }
}
Scotney answered 12/11, 2013 at 23:19 Comment(2)
Twitter callback url in your Twitter Dev application settings must be in http:// or https:// format, even though at runtime your android app will provide its own oauth://t4jsample valueWon
@Scotney Do you face same issue as this #24205355?Tomasatomasina
T
0

Have you seen the sign-in-with-twitter github project, it is based on twitter4j and implements Twitter sign in for Android.

Tiffie answered 26/5, 2016 at 18:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.