42

I'm using retrofit to get some data from the Flickr api. The method I'm making the call in looks like this:

public static List<String> getImageIds(int size) {
    Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
    Log.d("TEMP_TAG", "photo url: " + call.request().url().toString());
    photoIds = new ArrayList<String>();

    call.enqueue(new Callback<PhotosList>(){
        @Override
        public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
            Log.d("TEMP_TAG", "it's getting here");
            PhotosList photosList = response.body();
            List<Photo> photos = photosList.getPhotos().getPhoto();

            for(Photo photo : photos) {
                Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
                photoIds.add(photo.getId());
            }
        }

        @Override
        public void onFailure(Call<PhotosList> call, Throwable t) {
            // TODO: Clean up
            Log.d("TEMP_TAG", "photoId: ");
        }
    });
    Log.d("TEMP_TAG", "it's getting here too");
    return photoIds;
}

However it is never getting into the onResponse() method. The first log statement within onResponse() never prints, neither does the log statement in onFailure(). When I try entering the URL that is returned by call.request().url().toString() in the browser it works fine, and I get the expected JSON. Why is my enqueue() method never firing?

Thanks for any help!

intA
  • 2,513
  • 12
  • 41
  • 66
  • 1
    This isnt a real answer, but my personal suggestion is always use something like Charles or Postman when testing new network calls. That way you can see what you send, and what you receive in their original formats. – TooManyEduardos Aug 12 '17 at 04:18
  • Also, remove the log `Log.d("TEMP_TAG", "photo url: " + call.request().url().toString());` and see if it works (the call.request() element could be consuming the call before it even happens) – TooManyEduardos Aug 12 '17 at 04:20

3 Answers3

68

Use HttpLoggingInterceptor along with Retrofit.

If this helps, add this inside your build.gradle -

//Retrofit and OkHttp for Networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//Logging Network Calls
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'

Inside your APIClient class add this -

public class ApiClient {
    private static Retrofit retrofit = null;

    public static Retrofit getClient(){

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build();


        if(retrofit==null){
            retrofit = new Retrofit.Builder()
                    .baseUrl(BuildConfig.baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }
}

Kotlin Code

val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }

val client : OkHttpClient = OkHttpClient.Builder().apply {
            addInterceptor(interceptor)
        }.build()


fun getService(): Service {
        return Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(LiveDataCallAdapterFactory())
                .client(client)
                .build()
                .create(Service::class.java)
    }

And you will be able to log the Retrofit Network calls that you make.

Let me know if you need more information.

hsm59
  • 1,991
  • 19
  • 25
  • 2
    That's just logging. What about actual debugging? One with breakpoints? For some reason, getting the response-body's fields stays on "collecting data..." forever. See here: https://i.imgur.com/SCEL7K2.png . How could it be? What can I do to make it have the value ? – android developer Feb 17 '21 at 13:37
  • Based on the screenshot, the `response.body()` already shows the `errorCode` value to be `0`, moreover, you can use evaluate expression to run a particular command in debug mode. You can learn more about Evaluate Expression from [here](https://stackoverflow.com/a/44382411/1992823) – hsm59 Aug 24 '21 at 07:13
18

An OkHttp interceptor which logs HTTP request and response data.

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(logging)
    .build();

You can change the log level at any time by calling setLevel.

There are 4 levels: NONE, BASIC, HEADERS, BODY

To log to a custom location, pass a Logger instance to the constructor.

HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new 
Logger() {
@Override public void log(String message) {
    Log.d(TAG, "message: ");
    }
});

From Gradle

compile 'com.squareup.okhttp3:logging-interceptor:(insert latest version)'

Follow this reference

EDITED: I also found this library which has a very nice structure and clean log. Try it!!

phatnhse
  • 3,870
  • 2
  • 20
  • 29
  • Hmm, this doesn't seem to be doing anything for me. Used the above code and put the `HttpLoggingInterceptor` in the method making the calls, but nothing gets output. – intA Aug 12 '17 at 03:34
  • 1
    Did you add client for retrofit by using this Retrofit#client(client)? – phatnhse Aug 12 '17 at 03:36
  • Yes, I did add the `.client(client)` to the chain where I am building my Retrofit object – intA Aug 12 '17 at 03:44
  • Because OkHttp is designed at Builder pattern, so carefully implement OkHttp with HttpLoggingInterceptor before call .build() – phatnhse Aug 12 '17 at 03:46
  • You may want to add the code of how you're initializing Retrofit, Gson, and any adapter – TooManyEduardos Aug 12 '17 at 04:19
  • using java8: `HttpLoggingInterceptor logging = new HttpLoggingInterceptor((msg)-> { System.out.println(msg); });` – Leon Nov 24 '18 at 01:30
1

You can use the following class to log API calls

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor

object HTTPLogger {
    fun getLogger(): OkHttpClient {
        /*
         * OKHTTP interceptor to log all API calls
         */
        val interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        val client = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build()
        return client
    }
}

You can then call this class in your retrofit instance class like this

import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClientInstance {
    private var retrofit: Retrofit? = null
    val retrofitInstance: Retrofit?
        get() {
            if (retrofit == null) {
                retrofit = Retrofit.Builder()
                        .baseUrl(Constants.BASE_URL)
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .client(HTTPLogger.getLogger())
                        .build()
            }
            return retrofit
        }
}

The dependency required is

implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
Shubham Goel
  • 1,962
  • 17
  • 25