7

I've wrote some code to allow a user to login to his Twitter account and send Tweet using Twitter4j and following this tutorial.

Now I can also get the tweets of a public account using

ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setHttpConnectionTimeout(10000)
.setHttpReadTimeout(10000)
.setOAuthConsumerKey(Config.TWITTER_CONSUMER_KEY)
.setOAuthConsumerSecret(Config.TWITTER_CONSUMER_SECRET)
.setOAuthAccessToken(Utils.getPrefsString(getActivity(),
    TwitterPrefsFragment.PREF_KEY_OAUTH_TOKEN, "")) // empty if not authentified
.setOAuthAccessTokenSecret(Utils.getPrefsString(getActivity(),
    TwitterPrefsFragment.PREF_KEY_OAUTH_SECRET, "")); // empty if not authentified
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();

List<twitter4j.Status> statuses = twitter.getUserTimeline(SOME_PUBLIC_TWITTER_ACCOUNT, new Paging(1, 50));

but this only works when the user is authenticated and the app has the oauth token and secret in the preferences..

How can I get a Twitter public timeline with no Access Token, i.e. without having the user to authenticate?

EDIT

I'm reformulating my question to make it clearer:

I managed to authenticate my Twitter app and a user with the code given here.

Now, if the user is not logged in, how can I get a public timeline? In that case, there is no OAUTH_TOKEN and OAUTH_SECRET, and the request shown above does not work because an empty string is set to ConfigurationBuilder.setOAuthAccessToken and ConfigurationBuilder.setOAuthAccessTokenSecret.

So what is, if it exists, the request to get a public timeline, with no OAUTH_TOKEN and OAUTH_SECRET?

jul
  • 36,404
  • 64
  • 191
  • 318

4 Answers4

8

In your case, you should use Application-only authentication.

To do this with Twitter4J, try the following code

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb
    .setOAuthConsumerKey(<YOUR_CONSUMER_KEY>)
    .setOAuthConsumerSecret(<YOUR_CONSUMER_SECRET>)
    .setApplicationOnlyAuthEnabled(true); // IMPORTANT: set T4J to use App-only auth
    TwitterFactory tf = new TwitterFactory(cb.build());
    Twitter twitter = tf.getInstance();

    OAuth2Token token = twitter.getOAuth2Token();
    if (token != null) {
        System.out.println("Token Type  : " + token.getTokenType());
        System.out.println("Access Token: " + token.getAccessToken());
    }
    ResponseList<Status> list = twitter.getUserTimeline(783214); // Load @twitter's timeline without user login.

Key points of the above sample code:

  • Call setApplicationOnlyAuthEnabled(true) to enable Application-only authentication.
  • Get the access Token using getOAuth2Token() instead of getOAuthAccessToken()
TactMayers
  • 884
  • 8
  • 22
  • `The method setApplicationOnlyAuthEnabled(boolean) is undefined for the type ConfigurationBuilder` in Twitter4j latest stable version (3.0.3). It seems it's only available on 3.0.4, which is not stable yet. – jul Sep 12 '13 at 08:39
  • Then I'm afraid you cannot use Twitter4J to accomplish your goal, as it seems that using 3.0.4 is the only way to get App-only authentication to work. – TactMayers Sep 12 '13 at 08:54
  • I'll use the 3.0.4 dev version then, though I've just found you can use the solution given [here](http://www.heath-bar.com/blog/?p=599) too. – jul Sep 13 '13 at 06:17
7

This is certainly possible and I have already tried it. If your doubt is only regarding the Access Token and Access Token secret being empty, then you should try to use the Access Token provided in the app page. By app page I mean, the link where you have registered your twitter app.

If you go to dev.twitter.com ,and go to your app settings, you can see a consumer key, consumer secret, access token and access token secret. Make use of these and follow my below code and it should work,

ConfigurationBuilder cb = new ConfigurationBuilder();
        cb.setDebugEnabled(true)
                .setOAuthConsumerKey("B*************Q")
                .setOAuthConsumerSecret(
                        "l*************o")
                .setOAuthAccessToken(
                        "1*************s")
                .setOAuthAccessTokenSecret(
                        "s*************s");
        TwitterFactory tf = new TwitterFactory(cb.build());
        twitter = tf.getInstance();
        try {
            List<Status> statuses;
            String user;
            user = "Replace this with the screen name whose feeds you want to fetch";
            statuses = twitter.getUserTimeline(user);
            Log.i("Status Count", statuses.size() + " Feeds");

        } catch (TwitterException te) {
            te.printStackTrace();
        }

I used twitter 4j 3.03.jar for this.

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
  • I am getting a 'No authentication challenges found' exception when I try to execute your code. Can you help? – philip Jun 18 '14 at 06:48
2

How can I get a Twitter public timeline with no Access Token and Secret using Twitter4j?

Oh, that is very simple. YOU CAN'T.

Twitter a a data based company. 99% of the property of the company (I mean what the company owns) is data. It would be contra-productive, to give this data for free out to other people/businesses.

If the thing you want, would be possible, then there would be an easy way to backup the whole twitter database.

That is why they let you register an account for each application, that wants to use the API and limit each account to a certain amount of API calls per time frame. Of course they also want to prevent their network from spam etc.

Kenyakorn Ketsombut
  • 2,072
  • 2
  • 26
  • 43
  • I can't believe there is no way to get a public timeline without authentication. I can read https://twitter.com/google without being logged in. I could just parse the page and get the data.I'm not saying with no registered app. I actually have one with consumer key and secret, but I just don't want the user to have to enter its username/password. – jul Sep 11 '13 at 08:31
  • @jul sounds like you're confusing the concept of your app authenticating against the API versus the user authenticating themselves. – xdumaine Sep 12 '13 at 03:00
  • @jul Yes. Thanks for editing it. Of course you could parse the page, but if you do that too much, you will run into other preventive measures, like timeouts or captures. – Kenyakorn Ketsombut Sep 12 '13 at 07:16
1

If you want get tweets without user authenticating, you can use Application-only Authentication, because the user doesn´t need to login.

With Application-only authentication Twitter offers applications the ability to issue authenticated requests on behalf of the application itself (as opposed to on behalf of a specific user)

The application-only auth flow follows these steps:

An application encodes its consumer key and secret into a specially encoded set of credentials.

An application makes a request to the POST oauth2/token endpoint to exchange these credentials for a bearer token.

When accessing the REST API, the application uses the bearer token to authenticate.

NOTE: Because twitter4j has added this feature recently, you should use the last snapshot library.

An example using it:

private ConfigurationBuilder    builder;
private Twitter                 twitter;
private TwitterFactory          factory;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.init_act_layout);

// setup
builder = new ConfigurationBuilder();
builder.setUseSSL(true);
builder.setApplicationOnlyAuthEnabled(true);
builder.setOAuthConsumerKey(Constants.CONSUMER_KEY);
builder.setOAuthConsumerSecret(Constants.CONSUMER_SECRET);

Configuration configuration = builder.build();
factory = new TwitterFactory(configuration);
((MyApp) (MyApp.getApp())).setTFactory(factory);

if (isNeededTwitterAuth()) {
    twitter = factory.getInstance();
        //Get the token async and save it
}

    //Search tweets

}

/*
 * Checks if twitter access token is already saved in preferences
 * 
 * @return true if auth needed
 */
private boolean isNeededTwitterAuth() {
    SharedPreferences settings = getSharedPreferences(Constants.TWITTER_PREFERENCES, Context.MODE_PRIVATE);
    String twitterAccesToken = settings.getString("bearerAccessToken", "");
    String twitterTokenType = settings.getString("bearerTokenType", "");
    return ((twitterAccesToken.length() == 0) && (twitterTokenType.length() == 0));
}

}

To get the bearer token, do it out of Main UI thread to avoid Network exception, f.i. using AsyncTask:

@Override
    protected OAuth2Token doInBackground(Void... params) {
        OAuth2Token bearerToken = null;

        try {
            bearerToken = twitter.getOAuth2Token();
        } catch (TwitterException e) {
            e.printStackTrace();
        }
        return bearerToken;
    }

When you obtain the bearer token, save it:

SharedPreferences appSettings = getSharedPreferences(Constants.TWITTER_PREFERENCES, MODE_PRIVATE);
            SharedPreferences.Editor prefEditor = appSettings.edit();
            prefEditor.putString("bearerAccessToken", result.getAccessToken());
            prefEditor.putString("bearerTokenType", result.getTokenType());
            prefEditor.commit();

And to use the bearer token:

OAuth2Token bearerToken = new OAuth2Token(bearerTokenType, bearerAccesstoken);

        twitter.setOAuth2Token(bearerToken);

And search tweets (always out of Main thread):

@Override
 protected QueryResult doInBackground(Void... params) {

 twitter.setOAuth2Token(bearerToken);
 Query query = new Query();
 [...]
 result = twitter.search(query);

A complete explanation in the blog (in Spanish...)

And a complete example in the twitter4j github

Hope it helps!

Community
  • 1
  • 1
Josu Garcia de Albizu
  • 1,128
  • 2
  • 12
  • 22