0

I am trying to query Twitter on my android app and retrieve all the tweets related to the keyword "AgilebizKE" using retrofit. I am currently getting a 400 error code. After doing some research i have found that either my query parameters are wrong or my request isn't 'authorized'. However, i see no issues with my query parameters. Main Activity relevant code:

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.twitter.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        tweetAPI tweetapi = retrofit.create(tweetAPI.class);
        Call<List<tweet>> call = tweetapi.getTweets();
        call.enqueue(new Callback<List<tweet>>() {
            @Override
            public void onResponse(Call<List<tweet>> call, Response<List<tweet>> response) {
                if (!response.isSuccessful()) {
                    tweets_results.setText("code: " + response.code());
                    return;
                }
                List<tweet> tweets = response.body();
                for (tweet tweet : tweets){
                    String content = "";
                    content+="Created at: "+tweet.getCreated_at()+"\n";
                    content+="Text: "+tweet.getText()+"\n";
                    content+="Retweets: "+tweet.getRetweet_count()+"\n";
                    content+="Favs: "+tweet.getFavorite_count()+"\n\n";
                    tweets_results.append(content);
                }
            }

            @Override
            public void onFailure(Call<List<tweet>> call, Throwable t) {
                tweets_results.setText(t.getMessage());
            }
        });

Interface


public interface tweetAPI {
    @GET("1.1/search/tweets.json?q=AgilebizKE")
    Call<List<tweet>> getTweets();
}

Tweet pojo

ublic class tweet  {
    private String created_at;
    private String text;
    private String retweet_count;
    private String favorite_count;

    public String getCreated_at() {
        return created_at;
    }

    public String getText() {
        return text;
    }

    public String getRetweet_count() {
        return retweet_count;
    }

    public String getFavorite_count() {
        return favorite_count;
    }
}
  • Can you please post your LogCat? – Atish Agrawal Feb 21 '20 at 08:16
  • 2
    How are you generating the oAuth header? Are you able to access any other Twitter API? – Smile Feb 21 '20 at 08:17
  • From this document[https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets?]. This api require authentication. – Hello World Feb 21 '20 at 08:20
  • @HelloWorld In the documentation it appeared to suggest that only premium and enterprise search require authentication. –  Feb 21 '20 at 08:28
  • @Smile I'm not. I didn't know this was required for the standard tier of the search functionality. Can tou link me a resource on how to do this? –  Feb 21 '20 at 08:29
  • @Brokoth It's my bad. So sorry. – Hello World Feb 21 '20 at 08:30
  • 2
    Go to developer.twitter.com and generate consumer keys. Then check out [this](https://stackoverflow.com/a/59765764/1776132) answer for generating oAuth header in java or use [Twitter4j](http://twitter4j.org/en/) library. – Smile Feb 21 '20 at 08:35

1 Answers1

0

Ok so i decided to switch to using twitter4j instead of retrofit since it is much easier and quicker. For more details on this go to this site: http://twitter4j.org/

I will now explain how i implemented twitter search functionality for my use case.

Android Manifest

Add these permissions

 <uses-permission android:name="android.permission.WAKE_LOCK" />
 <uses-permission android:name="android.permission.INTERNET" />

build.gradle(Module: app)

Add this

 implementation files('libs/twitter4j-core-4.0.7.jar')

Next, you have to create a JobIntentService so as to run the network functions, that twitter4j requires, off the main thread. This is the video I used to better understand this concept: https://www.youtube.com/watch?v=B4gFbWnNpac&t=567s

TweetJobIntentService.java

Before proceeding any further, register your app and get its personal OAuth twitter credentials from the twitter for devs portal. Fill these credentials where I have indicated in the code sample below.

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.ArrayList;
import java.util.List;
import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;

public class TweetJobIntentService extends JobIntentService {
    private static final String TAG = "TweetJobIntentService";

    static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, TweetJobIntentService.class, 123, work);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");

    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        Log.d(TAG, "onHandleWork: ");
        List tweets = new ArrayList();
        Twitter twitter = new TwitterFactory().getInstance();
        twitter.setOAuthConsumer("Your_OAuthConsumerKey", "Your_AuthConsumerSecret");
        AccessToken accessToken = new AccessToken("Your_OAuthAccessToken", "Your_OAuthAccessTokenSecret");
        twitter.setOAuthAccessToken(accessToken);
        Query query = new Query(Your_search_Keyword);
        try {
            QueryResult result = twitter.search(query);
            for (Status status : result.getTweets()) {
                Log.d(TAG, status.getText());

            }
            if (isStopped()) return;
        } catch (TwitterException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDeastroy");
    }

    @Override
    public boolean onStopCurrentWork() {
        Log.d(TAG, "onStopCurrentWork");
        return super.onStopCurrentWork();
    }
}

Your retrieved tweets should be printed in logcat.

Your Main activity/fragment

Here, you will initiate/call your JobIntentService. For me, my service is initiated in a fragment in the onViewCreated method. Yours can be initiated following a button click or whatever you wish.

        Intent jobserviceIntent = new Intent(getActivity(), TweetJobIntentService.class);
        TweetJobIntentService.enqueueWork(getActivity(), jobserviceIntent);