Как регистрировать тело запроса и ответа с помощью Retrofit-Android?

129

Я не могу найти подходящие методы в Retrofit API для регистрации полных тел запросов / ответов. Я ожидал некоторой помощи в Profiler (но он предлагает только метаданные об ответе). Я пробовал установить уровень журнала в Builder, но мне это тоже не помогло:

RestAdapter adapter = (new RestAdapter.Builder()).
                setEndpoint(baseUrl).
                setRequestInterceptor(interceptor).
                setProfiler(profiler).
                setClient(client).
                setExecutors(MyApplication.getWebServiceThreadPool()).
                setLogLevel(LogLevel.FULL).
                setLog(new RestAdapter.Log() {
                    @Override
                    public void log(String msg) {
                        Log.i(TAG, msg);
                    }
                }).
                build();

РЕДАКТИРОВАТЬ: этот код сейчас работает. Не знаю, почему раньше не работало. Возможно, потому что я использовал старую версию дооснащения.

ягуар
источник
Вы когда-нибудь понимали это? В документации сказано, что FULLэто должно дать тело, но это не похоже.
theblang
1
@mattblang: я не знаю, что было не так раньше, но сейчас этот код работает.
Jaguar
Возможный дубликат Logging with Retrofit 2
bryant1410
Наверное, мгновенный запуск что-то испортил, если бы он не работал раньше
deathangel908

Ответы:

91

Использовал setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), мне помогло.
ОБНОВИТЬ.
Вы также можете попробовать использовать для отладки в retrofit.client.Responseкачестве модели ответа

Алексей Дзешко
источник
2
AndroidLog, что это за класс?
theblang
Поставляется с библиотекой Retrofit.
Alex Dzeshko
2
Понимаю. К сожалению, это не дает вам response body, хотя в документе говорится, что вы LogLevel.FULL должны предоставить вам response body.
theblang
Это можно увидеть с помощью «YOUR_LOG_TAG» в logcat Android на вкладке «Подробная информация».
Rajeesh
4
LogLevel.Full не существует в модификации 2
121

Модернизация 2.0 :

ОБНОВЛЕНИЕ: @ by Marcus Pöhls

Вход в систему Retrofit 2

Retrofit 2 полностью полагается на OkHttp для любых сетевых операций. Поскольку OkHttp является одноранговой зависимостью Retrofit 2, вам не нужно будет добавлять дополнительную зависимость после выпуска Retrofit 2 в качестве стабильного выпуска.

OkHttp 2.6.0 поставляется с перехватчиком журналов в качестве внутренней зависимости, и вы можете напрямую использовать его для своего клиента Retrofit. Retrofit 2.0.0-beta2 по-прежнему использует OkHttp 2.5.0. В будущих выпусках будет увеличена зависимость от более высоких версий OkHttp. Вот почему вам нужно вручную импортировать перехватчик журналов. Добавьте следующую строку в свой импорт gradle в файле build.gradle, чтобы получить зависимость перехватчика ведения журнала.

compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'

Вы также можете посетить страницу Square GitHub об этом перехватчике.

Добавление регистрации в дооснащение 2

При разработке приложения и в целях отладки хорошо иметь интегрированную функцию журнала для отображения информации о запросах и ответах. Поскольку ведение журнала по умолчанию больше не интегрировано в Retrofit 2, нам нужно добавить перехватчик журнала для OkHttp. К счастью, OkHttp уже поставляется с этим перехватчиком, и вам нужно только активировать его для своего OkHttpClient.

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();  
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();   
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging);  // <-- this is the important line!
Retrofit retrofit = new Retrofit.Builder()  
        .baseUrl(API_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(httpClient.build())
        .build();

Мы рекомендуем добавить запись в журнал в качестве последнего перехватчика, потому что это также будет регистрировать информацию, которую вы добавили с предыдущими перехватчиками в свой запрос.

Уровни журнала

Запись слишком большого количества информации взорвет ваш монитор Android, поэтому перехватчик журналов OkHttp имеет четыре уровня журнала: NONE, BASIC, HEADERS, BODY. Мы проведем вас через каждый уровень журнала и опишем их результат.

дополнительную информацию, пожалуйста, посетите: Retrofit 2 - Log Requests and Responses

СТАРЫЙ ОТВЕТ:

больше нет входа в Retrofit 2. Команда разработчиков удалила функцию ведения журнала. Честно говоря, функция регистрации в любом случае не была такой надежной. Джейк Уортон прямо заявил, что зарегистрированные сообщения или объекты являются предполагаемыми значениями, и их истинность не может быть подтверждена. Фактический запрос, который поступает на сервер, может иметь измененное тело запроса или что-то еще.

Несмотря на то, что по умолчанию интегрированное ведение журнала отсутствует, вы можете использовать любое средство ведения журнала Java и использовать его в настраиваемом перехватчике OkHttp.

дополнительную информацию о Retrofit 2 см. в разделе Retrofit - Начало работы и создание клиента Android.

Дхавал Дживани
источник
1
Также есть специальный пост для входа в Retrofit 2.0: futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek
Отличный способ все усложнить, чем должно быть. Напоминает мне регистрацию Джерси 1 против Джерси 2. Еще шаблонный код ....
breakline
Добавление перехватчиков таким образом теперь приведет к исключению UnsupportedOperationException в OkHttp v3. Новый способ: OkHttpClient.Builder (). AddInterceptor (logging) .build () github.com/square/okhttp/issues/2219
Amagi82
@JawadLeWywadi да, используя этот код, вы можете распечатать тело
Дхавал Дживани
Для Retrofit 2 это намного проще.
Gary99
31

Обновление для Retrofit 2.0.0-beta3

Теперь вам нужно использовать okhttp3 со строителем. Также не подойдет старый перехватчик. Этот ответ адаптирован для Android.

Вот вам быстрая копия и вставка с новым материалом.

1. Измените свой файл gradle на

  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. Проверьте этот пример кода:

с новым импортом. Вы можете удалить Rx, если вы его не используете, а также удалить то, что вы не используете.

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);
    }
  }
}

бонус

Я знаю, что это оффтоп, но мне это нравится.

Если есть код ошибки http: unauthorized , вот перехватчик. Я использую eventbus для передачи события.

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;
  }
}

код взять из https://github.com/AndreiD/UltimateAndroidTemplateRx (мой проект).

OWADVL
источник
9

Похоже, что нет способа сделать базовый + body, но вы можете использовать FULL и фильтровать заголовки, которые вам не нужны.

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();

Похоже, что при переопределении журнала к телу добавляется префикс, похожий на

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

так что должно быть легко регистрировать базовый + тело, настраивая настраиваемый фильтр. Я использую черный список, но белый список также может быть использован в зависимости от ваших потребностей.

Xeridea
источник
4

приведенный ниже код работает как с заголовком, так и без заголовка для печати запроса и ответа журнала. Примечание: просто прокомментируйте строку .addHeader (), если не используете заголовок.

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();
Мукеш Пармар
источник
3

Надеюсь, этот код поможет вам в логировании.
вам просто нужно добавить перехватчик в свой файл Build.Gradlethen make RetrofitClient.

Первый шаг

Добавьте эту строку в свой build.gradle

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

Второй шаг

Сделайте своего клиента для модернизации


   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;
    }
}

призвание

RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 
Тальха Билал
источник
2

Если вы используете Retrofit2 и okhttp3, вам нужно знать, что Interceptor работает по очереди. Поэтому добавьте loggingInterceptor в конце после других ваших перехватчиков:

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG)
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);

 new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(new CatalogInterceptor(context))
                .addInterceptor(new OAuthInterceptor(context))
                .authenticator(new BearerTokenAuthenticator(context))
                .addInterceptor(loggingInterceptor)//at the end
                .build();
NickUnuchek
источник
0

Для студии android до версии 3.0 (с использованием android motinor)
https://futurestud.io/tutorials/retrofit-2-log-requests-and-responses
https://www.youtube.com/watch?v=vazLpzE5y9M

А для студии Android версии 3.0 и выше (использование профилировщика Android в качестве монитора Android заменяется профилировщиком Android)
https://futurestud.io/tutorials/retrofit-2-analyze-network-traffic-with-android-studio-profiler

shehzy
источник