How to log request and response body with Retrofit-Android?

前端 未结 9 2029
盖世英雄少女心
盖世英雄少女心 2020-11-28 21:35

I can\'t find relevant methods in the Retrofit API for logging complete request/response bodies. I was expecting some help in the Profiler (but it only offers meta-data abou

相关标签:
9条回答
  • 2020-11-28 21:48

    I used setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), it helped me.
    UPDATE.
    You can also try for debug purpose use retrofit.client.Response as response model

    0 讨论(0)
  • 2020-11-28 21:54

    I hope this code will help you to logging .
    you just need to add interceptor in your Build.Gradle then make RetrofitClient .

    First Step

    Add this line to your build.gradle

     implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' 
    

    Second Step

    Make your Retrofit Client

    
       public class RetrofitClient {
    
        private Retrofit retrofit;
        private static OkHttpClient.Builder httpClient =
                new OkHttpClient.Builder();
        private static RetrofitClient instance = null;
        private static ApiServices service = null;
        private static HttpLoggingInterceptor logging =
                new HttpLoggingInterceptor();
    
        private RetrofitClient(final Context context) {
            httpClient.interceptors().add(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                    Request originalRequest = chain.request();
                    Request.Builder builder = originalRequest.newBuilder().
                            method(originalRequest.method(), originalRequest.body());
                    okhttp3.Response response = chain.proceed(builder.build());
                    /*
                    Do what you want
                     */
                    return response;
                }
            });
    
            if (BuildConfig.DEBUG) {
                logging.setLevel(HttpLoggingInterceptor.Level.BODY);
                // add logging as last interceptor
                httpClient.addInterceptor(logging);
            }
    
            retrofit = new Retrofit.Builder().client(httpClient.build()).
                    baseUrl(Constants.BASE_URL).
                    addConverterFactory(GsonConverterFactory.create()).build();
            service = retrofit.create(ApiServices.class);
        }
    
    
        public static RetrofitClient getInstance(Context context) {
            if (instance == null) {
                instance = new RetrofitClient(context);
            }
            return instance;
        }
    
        public ApiServices getApiService() {
            return service;
        }
    }
    

    Calling

    RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 
    
    
    0 讨论(0)
  • 2020-11-28 21:58

    Update for Retrofit 2.0.0-beta3

    Now you have to use okhttp3 with builder. Also the old interceptor will not work. This response is tailored for Android.

    Here's a quick copy paste for you with the new stuff.

    1. Modify your gradle file to

      compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
      compile "com.squareup.retrofit2:converter-gson:2.0.0-beta3"
      compile "com.squareup.retrofit2:adapter-rxjava:2.0.0-beta3"
      compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
    

    2. Check this sample code:

    with the new imports. You can remove Rx if you don't use it, also remove what you don't use.

    import okhttp3.OkHttpClient;
    import okhttp3.logging.HttpLoggingInterceptor;
    import retrofit2.GsonConverterFactory;
    import retrofit2.Retrofit;
    import retrofit2.RxJavaCallAdapterFactory;
    import retrofit2.http.GET;
    import retrofit2.http.Query;
    import rx.Observable;
    
    public interface APIService {
    
      String ENDPOINT = "http://api.openweathermap.org";
      String API_KEY = "2de143494c0b2xxxx0e0";
    
      @GET("/data/2.5/weather?appid=" + API_KEY) Observable<WeatherPojo> getWeatherForLatLon(@Query("lat") double lat, @Query("lng") double lng, @Query("units") String units);
    
    
      class Factory {
    
        public static APIService create(Context context) {
    
          OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
          builder.readTimeout(10, TimeUnit.SECONDS);
          builder.connectTimeout(5, TimeUnit.SECONDS);
    
          if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
            builder.addInterceptor(interceptor);
          }
    
          //Extra Headers
    
          //builder.addNetworkInterceptor().add(chain -> {
          //  Request request = chain.request().newBuilder().addHeader("Authorization", authToken).build();
          //  return chain.proceed(request);
          //});
    
          builder.addInterceptor(new UnauthorisedInterceptor(context));
          OkHttpClient client = builder.build();
    
          Retrofit retrofit =
              new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
    
          return retrofit.create(APIService.class);
        }
      }
    }
    

    Bonus

    I know it's offtopic but I find it cool.

    In case there's an http error code of unauthorized, here is an interceptor. I use eventbus for transmitting the event.

    import android.content.Context;
    import android.os.Handler;
    import android.os.Looper;
    import com.androidadvance.ultimateandroidtemplaterx.BaseApplication;
    import com.androidadvance.ultimateandroidtemplaterx.events.AuthenticationErrorEvent;
    
    import de.greenrobot.event.EventBus;
    import java.io.IOException;
    import javax.inject.Inject;
    import okhttp3.Interceptor;
    import okhttp3.Response;
    
    public class UnauthorisedInterceptor implements Interceptor {
    
      @Inject EventBus eventBus;
    
      public UnauthorisedInterceptor(Context context) {
        BaseApplication.get(context).getApplicationComponent().inject(this);
      }
    
      @Override public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        if (response.code() == 401) {
          new Handler(Looper.getMainLooper()).post(() -> eventBus.post(new AuthenticationErrorEvent()));
        }
        return response;
      }
    }
    

    code take from https://github.com/AndreiD/UltimateAndroidTemplateRx (my project).

    0 讨论(0)
  • 2020-11-28 22:01

    There doesn't appear to be a way to do basic + body, but you can use FULL and filter the headers you don't want.

    RestAdapter adapter = new RestAdapter.Builder()
                              .setEndpoint(syncServer)
                              .setErrorHandler(err)
                              .setConverter(new GsonConverter(gson))
                              .setLogLevel(logLevel)
                              .setLog(new RestAdapter.Log() {
                                  @Override
                                  public void log(String msg) {
                                      String[] blacklist = {"Access-Control", "Cache-Control", "Connection", "Content-Type", "Keep-Alive", "Pragma", "Server", "Vary", "X-Powered-By"};
                                      for (String bString : blacklist) {
                                          if (msg.startsWith(bString)) {
                                              return;
                                          }
                                      }
                                      Log.d("Retrofit", msg);
                                  }
                              }).build();
    

    It appears that when overriding the log, the body is prefixed with a tag similar to

    [ 02-25 10:42:30.317 25645:26335 D/Retrofit ]
    

    so it should be easy to log basic + body by adjusting the custom filter. I am using a blacklist, but a whitelist could also be used depending on your needs.

    0 讨论(0)
  • 2020-11-28 22:02

    below code is working for both with header and without header to print log request & response. Note: Just comment .addHeader() line if are not using header.

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    //.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                    .addNetworkInterceptor(new Interceptor() {
    
                        @Override
    
                        public okhttp3.Response intercept(Chain chain) throws IOException {
                            Request request = chain.request().newBuilder()
                                    // .addHeader(Constant.Header, authToken)
                                       .build();
                            return chain.proceed(request);
                        }
                    }).build();
    
            final Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Constant.baseUrl)
                    .client(client) // This line is important
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
    0 讨论(0)
  • 2020-11-28 22:02

    ZoomX — Android Logger Interceptor is a great interceptor can help you to solve your problem.

    0 讨论(0)
提交回复
热议问题