6
votes

What I Have Tried:

I already have registered an app in twitter and got Consumer Key and Secret.Even I got various codes to login with twitter.These are what I have tried from:

http://thetechnib.blogspot.com/2011/01/android-sign-in-with-twitter.html

[This link is dead, you may view an archive here]
http://www.android10.org/index.php/articleslibraries/291-twitter-integration-in-your-android-application

Problem I have:

Till now,above code takes me to twitter login and let me sign in and have a PIN to complete the login process.But I have no idea how to use it to get my app working.I checked the whole code but found nothing related to pin.

Secondly,when I registered my app on twitter,it asked for Callback URL but as it was written that its really not needed,i skipped specifying.(Even I don't know what it should be!)

And hence,I am giving null as CallbackURL in my app.

Can anyone suggest me,how can I use this PIN to complete login process and get user back to my app's main activity? Is it the callback url which is causing problem or something else I am doing wrong at?

Please reply.Any help appriciated! Thanks.

EDIT :

As suggested by Frankenstein,I tried code at github.com/ddewaele/AndroidTwitterSample/downloads

I added my consumer key and consumer secret along with callback url:

public static final String OAUTH_CALLBACK_SCHEME= "x-oauthflow-twitter";
public static final String OAUTH_CALLBACK_HOST= "callback";
public static final String OAUTH_CALLBACK_URL= OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;

but it gives me this error:

Logcat:

11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081): Error during OAUth retrieve request token
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081): oauth.signpost.exception.OAuthNotAuthorizedException: Authorization failed (server replied with a 401). This can happen if the consumer key was not correct or the signatures did not match.
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:239)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:69)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at com.ecs.android.sample.twitter.OAuthRequestTokenTask.doInBackground(OAuthRequestTokenTask.java:55)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at com.ecs.android.sample.twitter.OAuthRequestTokenTask.doInBackground(OAuthRequestTokenTask.java:1)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at android.os.AsyncTask$2.call(AsyncTask.java:185)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
11-29 11:56:56.249: E/com.ecs.android.sample.twitter.OAuthRequestTokenTask(3081):   at java.lang.Thread.run(Thread.java:1096)

Also shows me black screen when i click on TWEET button,instead of taking me to sign in screen of twitter.

Omg,I am going to be crazy...have been trying since two days! :( please help.

3
Are you already handling the return from the authorization process and storing the access token?jmcdale
Well...I don't know whether it saves token or not in code because i am new to OAuth. But looking at code,i don't think the token is saved.Hiral Vadodaria

3 Answers

9
votes

It's because your app is registered as a desktop client. To overwrite callback URL, your app need to be registered as a browser client.

Try configuring a dummy callback URL (http://example.com/ or whatever you want) at https://dev.twitter.com/apps/[appid]/settings > Callback URL and your app will be recognized as a browser client.

Then try @Frankenstein or @jamn224 code.

7
votes

First, you need to authenticate properly:

try{
        consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        provider = new DefaultOAuthProvider("http://twitter.com/oauth/request_token", "http://twitter.com/oauth/access_token", "http://twitter.com/oauth/authorize");
        String authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL);

        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));

    }catch(Exception e){
        Log.e(TAG,e+"");
    }

The necessities for CALLBACK_URL need to be set in the Manifest file (refer to Frankenstein's answer). The above code starts an intent to perform the authorization at Twitter's server. The callback information is necessary so the intent knows what app to return to after the authorization procedure.

Then we need to handle the return to the app after authenticating at Twitter:

    @Override
public void onResume(){
    super.onResume();

    if (this.getIntent()!=null && this.getIntent().getData()!=null){
        Uri uri = this.getIntent().getData();

        //handle returning from authenticating the user
        if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
            String verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
            String token = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_TOKEN);
            try {  
                Twitter t = new TwitterFactory().getInstance();
                t.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);

                // Get Access Token and store it  
                rToken = new RequestToken(token, CONSUMER_SECRET);
                AccessToken aToken = t.getOAuthAccessToken(rToken);
                storeAccessToken(aToken);  

                //send to checkLoginState again since we have authorization now!
                checkLoginState(); 

           } catch (Exception e) {  
               Log.e(TAG, e+"");  
           }  
          }  
         }
}//end onResume

This code grabs the data from the returning intent, among which is the info to grab the authorization token. "storeAccessToken(aToken)" is a short method i wrote that stores the token in the app's preferences so that we don't need to reauthorize every time the app is opened.

Now that we have an authorization token, we can use it authorize a Twitter instance:

twitter = new TwitterFactory().getInstance();
        twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        twitter.setOAuthAccessToken(aToken);

The above variable "twitter" is now authorized and can do its thing.

5
votes

you should be writing callback as this in manifest to your activity

<activity android:name="com.apps.twitter.PrepareRequestTokenActivity"
            android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:screenOrientation="portrait">
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="x-oauthflow-twitter" android:host="callback" />
            </intent-filter>
</activity>

And in the Constant File

final public static String  CALLBACK_SCHEME = "x-oauthflow-twitter";    
final public static String  CALLBACK_URL = CALLBACK_SCHEME + "://callback";