1
votes

First off, I've looked at every question on the topic in this site at least twice, and I haven't been able to find anything.

I've used some tutorials to create a simple Twitter client with Twitter4J that only provides OAuth login. The code takes the user to the browser, where the accept the OAuth, and then the browser returns me to my app.

However, I'm unable to get the OAuth Access token using the method getOAuthAccessToken(), in the method onNewIntent(Intent intent) and the log shows that the error is simply Twitter Login Error > null.

I've tried changing the location of the getOAuthAccessToken() to with an onResume, an onNewIntent, I've made the Activity a singleInstance and a singleTask, and I've set the date and time correctly. If anyone could help me get the access token from Twitter upon returning from the browser, that would be great, thanks! Here's my code:

public class mAppActivity extends Activity {

    // constants
    static final String TWITTER_CONSUMER_KEY = "";
    static final String TWITTER_CONSUMER_SECRET = 
            "";

    // preference constants
    static final 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 = "isTwitterLoggedIn";

    static final String TWITTER_CALLBACK_URL = "callback://x-oauthflow-twitter";

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

    // Buttons
    Button btnLoginTwitter;
    Button btnUpdateStatus;
    Button btnLogoutTwitter;

    // EditText for update
    EditText txtUpdate;

    // lbl update
    TextView lblUpdate;
    TextView lblUserName;

    // ProgressDialog
    ProgressDialog pdialog;

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

    // SharedPreferences
    private static SharedPreferences mSharedPreferences;

    // Internet ConnectionDetector
    private ConnectionDetector cd;

    // AlertDialogManager
    AlertDialogManager alert = new AlertDialogManager();

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

        cd = new ConnectionDetector(getApplicationContext());

        // check if connected to Internet
        if (!cd.isConnectingToInternet()) {
            // show error message
            alert.showAlertDialog(mAppActivity.this, 
                    "Internet Connection Error", 
                    "Please connect to working Internet connection", 
                    false);
            // stop code by returning
            return;
        }

        // check if Twitter keys are set
        if (TWITTER_CONSUMER_KEY.trim().length() == 0 ||
            TWITTER_CONSUMER_SECRET.trim().length() == 0) {
            // show error message
            alert.showAlertDialog(mAppActivity.this, 
                    "Twitter OAuth Tokens Error",
                    "Please set your Twitter OAuth tokens first!", 
                    false);

            // stop code by returning
            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);

        // SharedPreferences
        mSharedPreferences = getApplicationContext()
                            .getSharedPreferences("MyPrefs", 0);

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

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

        /**
         * Twitter logout button click 
         */
        btnLogoutTwitter.setOnClickListener(new View.OnClickListener() {

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

    /**
     * Function to log in to Twitter
     */
    private void loginToTwitter() {

        // Check if already logged in
        if (!isTwitterLoggedInAlready()) {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setUseSSL(true);
            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);
                        mAppActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
                                .parse(requestToken.getAuthenticationURL())));

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

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

    /**
     * Checks if user is already logged in using Twitter login 
     * fetched from Shared Preferences
     */
    private boolean isTwitterLoggedInAlready() {
        // return Twitter login status from SharedPreferences
        return mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false); 
    }

    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        /** 
         * This if condition is tested user is 
         * redirected from Twitter page. Parse the URI to OAuth Verifier
         */
        Uri uri = intent.getData();

        Toast.makeText(getApplicationContext(),
                uri.toString(), Toast.LENGTH_LONG).show(); 

        if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {   

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

            try {                           
                // get the access token
                        mAppActivity.this.accessToken = 
                                twitter.getOAuthAccessToken(
                                requestToken);

                        // SharedPreferences
                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);

                // get user details from Twitter
                // for now only username is being gotten
                long userID = accessToken.getUserId();
                User user = twitter.showUser(userID);
                String username = user.getName();

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

}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.messagingapplication"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <!-- Permission - Internet Connect -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- Network State Permissions -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.messagingapplication.mAppActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask">
            <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="x-oauthflow-twitter"
                    android:scheme="callback" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.messagingapplication.MAppMainActivity"
            android:label="@string/title_activity_mapp_main" >
        </activity>
        <activity
            android:name="com.example.messagingapplication.Teest"
            android:label="@string/title_activity_teest" >
        </activity>
    </application>

</manifest>
3

3 Answers

0
votes

You need to pass in the OAuth verifier string, which you've retrieved out of the query parameters but haven't passed in correctly to the getOAuthAccessToken method:

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

        try {                           
            // get the access token
                    mAppActivity.this.accessToken = 
                            twitter.getOAuthAccessToken(
                            requestToken,
                            verifier); // You forgot to pass this in.
0
votes

I fixed that same issue. its blocking on your ui. u just try it in asynctask. u just call that code inside a asynctask.

requestToken = twitter.getOAuthRequestToken(TWITTER_CALLBACK_URL); or

like this,

class TwitterLogin extends AsyncTask<String, String, String> 
    {

        @Override
        protected String doInBackground(String... params) 
        {
            // TODO Auto-generated method stub

            Uri uri = getIntent().getData();                
            if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL))
            {
                String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
                try 
                {
                    AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier);
                    // Shared Preferences
                    Editor e = loginPrefs.edit();
                    e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                    e.putString(PREF_KEY_OAUTH_SECRET,accessToken.getTokenSecret());
                    e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                    e.commit();

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


                    long userID = accessToken.getUserId();
                    User user = twitter.showUser(userID);
                    String username = user.getName();
                    Log.e("UserID: ", "userID: "+userID+""+username);

                    Log.v("Welcome:","Thanks:"+Html.fromHtml("<b>Welcome " + username + "</b>"));
                } 
                catch (Exception e) 
                {
                    Log.e("Twitter Login Error", "> " + e.getMessage());
                }
            }

            return null;
        }

        @Override
        protected void onPostExecute(String result) 
        {
            // TODO Auto-generated method stub
            super.onPostExecute(result);

        }

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

        }
    }
0
votes

The problem I thing you are run the app in mobile device not emulator , you need to add Thread to get the response from twitter CallBack