Android: Login with Twitter using Twitter4J

17,609

Solution 1

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.

Solution 2

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.

Solution 3

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";
Share:
17,609
Hiral Vadodaria
Author by

Hiral Vadodaria

Focused on : Making the UI/UX better for the products I work on, Creating beautiful mock ups for website/mobile application, Designing e-mailers, brochures,banners,table tops etc.(not a graphic designer though), Following UX procedure through sketches, user and site flow, wire frames and prototypes. Hands on : Transforming mock ups to HTML/CSS/jQuery based digital pages, Creating responsive screens using bootstrap and other libraries, Integrating jQuery libraries to create final working sections of page Learning : AngularJS, Basic graphic designing using Adobe Illustrator, Taking interaction design course Also know : Android, basic PHP

Updated on June 11, 2022

Comments

  • Hiral Vadodaria
    Hiral Vadodaria about 2 years

    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.

  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    I have tried this with code specified in 2nd reference link of my question.But unfortunately,it doesn't work for me. :( anyways,thanks.
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    Also giving "" as CallbackURL lets me sign in with twitter but just I am stuck at is,I don't know what to do with the PIN i get to complete sign in process.
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    Thanks for the reply.I will look into this.
  • jmcdale
    jmcdale over 12 years
    Oops... an important thing to mention is that I am using the open source signpost libraries for assistance with the oAuth procedures. I use the commons library and the core library, both of which can be found here
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    Can you please tell me how to store the tokens? I mean,can you give me codes of methods storeAccessToken(aToken) and checkLoginState() as well?
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    1 more question,won't it give me PIN to complete the login process even once i get to sign into twitter using this code? my question is only that,how to use that PIN in our app.Even if we get user to enter pin somewhere in our app,how would we use it and prevent him entering everytime he open the app?
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    Thanks for the response. I will surely try and let you know.
  • jmcdale
    jmcdale over 12 years
    I've never needed to use a PIN in my authorization process... so I can't help you there, sorry. public void storeAccessToken(AccessToken aToken){SharedPreferences.Editor editor = settings.edit(); editor.putString(PREFS_TWITTER_USER_TOKEN, aToken.getToken()); editor.putString(PREFS_TWITTER_USER_SECRET, aToken.getTokenSecret()); editor.commit();} As for checkLoginState(), it's just an if statement. It checks to see if I've stored aToken. If I have, then create a Twitter instance and do whatever. If not, then run authentication procedures.
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    I tried with someone else's Key-Secret pair and it worked perfectly.So can there be problem with just my pair of the same? if so,what can it be?
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    Even i tried deleting the app and creating a new one on dev.twitter account but even new pair doesn't seem to be working! :(
  • jmcdale
    jmcdale over 12 years
    That is strange. I don't see why another key-secret would be working and not yours.
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    I got the solution.I didn't give callback url in twitter registration.it was just blank so twitter was considering my app as desktop app and hence causing problem.Setting a url there solved my issue. thanks anyways!! :)
  • Someone Somewhere
    Someone Somewhere about 11 years
    Question: does the AccessToken expire ?