2015-09-11 3 views
212

Я пытаюсь получить точный JSON, который отправляется в запрос. Вот мой код:Регистрация с дооснащением 2

OkHttpClient client = new OkHttpClient(); 
client.interceptors().add(new Interceptor(){ 
    @Override public com.squareup.okhttp.Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 
     Log.e(String.format("\nrequest:\n%s\nheaders:\n%s", 
          request.body().toString(), request.headers())); 
     com.squareup.okhttp.Response response = chain.proceed(request); 
     return response; 
    } 
}); 
Retrofit retrofit = new Retrofit.Builder() 
    .baseUrl(API_URL) 
    .addConverterFactory(GsonConverterFactory.create()) 
    .client(client).build(); 

Но я вижу только это в журналах:

request: 
[email protected] 
headers: 
Content-Type: application/vnd.ll.event.list+json 

Как я должен делать правильное ведение журнала, учитывая удаление setLog() и setLogLevel(), которые мы использовали для использования с Модернизация 1?

ответ

457

В Модернизированный 2 следует использовать HttpLoggingInterceptor.

Добавить зависимость в build.gradle:

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

Создать Retrofit объект как следующее:

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

Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl("https://backend.example.com") 
     .client(client) 
     .addConverterFactory(GsonConverterFactory.create()) 
     .build(); 

return retrofit.create(ApiClient.class); 

выше решение, которое дает вам LogCat сообщения очень похожи на старые, установленные

setLogLevel(RestAdapter.LogLevel.FULL) 

В случае java.lang.ClassNotFoundException:

Старая версия для модернизации может потребовать более старую версию logging-interceptor. Взгляните на разделы комментариев.

+20

Это было добавлено в OkHttp всего через 15 дней после моего вопроса, приятно, что сообщество должно так быстро воздействовать! – Gabor

+0

Я просто беру эту ошибку: 'Не удалось решить: om.squareup.okhttp: logging-interceptor: 2.6.0-SNAPSHOT' Что случилось? –

+0

@YuriyKolbasinskiy Проверьте, что вы добавили 'maven {url 'http://oss.sonatype.org/content/repositories/snapshots'}' – GuillermoMP

-10

Эй, ребята, я уже нашел решение:

public static <T> T createApi(Context context, Class<T> clazz, String host, boolean debug) { 
    if (singleton == null) { 
     synchronized (RetrofitUtils.class) { 
      if (singleton == null) { 
       RestAdapter.Builder builder = new RestAdapter.Builder(); 
       builder 
         .setEndpoint(host) 
         .setClient(new OkClient(OkHttpUtils.getInstance(context))) 
         .setRequestInterceptor(RequestIntercepts.newInstance()) 
         .setConverter(new GsonConverter(GsonUtils.newInstance())) 
         .setErrorHandler(new ErrorHandlers()) 
         .setLogLevel(debug ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)/*LogLevel.BASIC will cause response.getBody().in() close*/ 
         .setLog(new RestAdapter.Log() { 
          @Override 
          public void log(String message) { 
           if (message.startsWith("{") || message.startsWith("[")) 
            Logger.json(message); 
           else { 
            Logger.i(message); 
           } 
          } 
         }); 
       singleton = builder.build(); 
      } 
     } 
    } 
    return singleton.create(clazz); 
} 
+0

обратного вызова setLog «s может вводить каждый журнал –

+0

это использует модифицированную v1, v2 не – Gabor

+0

Будет ли это работать на Retrofit2? –

4

Я не знаю, если setLogLevel() будет возвращать в окончательной версии 2.0 Модернизированный но теперь вы можете использовать перехватчик для регистрации.

Хорошим примером может найти в OkHttp вики: https://github.com/square/okhttp/wiki/Interceptors

OkHttpClient client = new OkHttpClient(); 
client.interceptors().add(new LoggingInterceptor()); 

Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl("http://www.yourjsonapi.com") 
     .addConverterFactory(GsonConverterFactory.create()) 
     .client(client) 
     .build(); 
+0

вы либо не читали мой вопрос, либо не читали страницу, на которую вы ссылаетесь ... потому что LoggingInterceptor не пытается регистрировать тело запроса (и поэтому не решает мою проблему) – Gabor

+0

Я получаю «UnsupportedOperationException» – Choletski

5

Попробуйте это:.

Request request = chain.request(); 
Buffer buffer = new Buffer(); 
request.body().writeTo(buffer); 
String body = buffer.readUtf8(); 

После этого, в body есть JSON вы заинтересованы в

+1

как можно распечатать ответ тела? –

+3

@GilbertoIbarra use 'String bodyString = response.body(). String(); \t \t \t \t log (bodyString); response = response.newBuilder(). Body (ResponseBody.create (response.body(). ContentType(), bodyString)). Build(); '(Вы не можете прочитать тело ответа более одного раза, так что вам нужно будет создать новый ответ с помощью строителя) –

+0

Это костыль, который нам больше не нужен. Вот пример рабочего журнала: http://stackoverflow.com/a/36847027/2557258 – Yazon2006

9

Вот Interceptor, который регистрирует тела запроса и ответа (используя Timber, на основе примера из документов OkHttp и некоторых других SO ответы):

public class TimberLoggingInterceptor implements Interceptor { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 

     long t1 = System.nanoTime(); 
     Timber.i("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers()); 
     Timber.v("REQUEST BODY BEGIN\n%s\nREQUEST BODY END", bodyToString(request)); 

     Response response = chain.proceed(request); 

     ResponseBody responseBody = response.body(); 
     String responseBodyString = response.body().string(); 

     // now we have extracted the response body but in the process 
     // we have consumed the original reponse and can't read it again 
     // so we need to build a new one to return from this method 

     Response newResponse = response.newBuilder().body(ResponseBody.create(responseBody.contentType(), responseBodyString.getBytes())).build(); 

     long t2 = System.nanoTime(); 
     Timber.i("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1)/1e6d, response.headers()); 
     Timber.v("RESPONSE BODY BEGIN:\n%s\nRESPONSE BODY END", responseBodyString); 

     return newResponse; 
    } 

    private static String bodyToString(final Request request){ 

     try { 
      final Request copy = request.newBuilder().build(); 
      final Buffer buffer = new Buffer(); 
      copy.body().writeTo(buffer); 
      return buffer.readUtf8(); 
     } catch (final IOException e) { 
      return "did not work"; 
     } 
    } 
} 
+0

здесь более простой пример: http://stackoverflow.com/a/36847027/2557258 – Yazon2006

+0

это было именно то, что я искал спасибо! – Informatic0re

+0

Это не работает для нескольких перехватчиков – abbath0767

4

Для тех, кто нуждается в высокой протоколирование уровня в Модернизированный, используйте перехватчик как этот

public static class LoggingInterceptor implements Interceptor { 
    @Override public Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 
     long t1 = System.nanoTime(); 
     String requestLog = String.format("Sending request %s on %s%n%s", 
       request.url(), chain.connection(), request.headers()); 
     //YLog.d(String.format("Sending request %s on %s%n%s", 
     //  request.url(), chain.connection(), request.headers())); 
     if(request.method().compareToIgnoreCase("post")==0){ 
      requestLog ="\n"+requestLog+"\n"+bodyToString(request); 
     } 
     Log.d("TAG","request"+"\n"+requestLog); 

     Response response = chain.proceed(request); 
     long t2 = System.nanoTime(); 

     String responseLog = String.format("Received response for %s in %.1fms%n%s", 
       response.request().url(), (t2 - t1)/1e6d, response.headers()); 

     String bodyString = response.body().string(); 

     Log.d("TAG","response"+"\n"+responseLog+"\n"+bodyString); 

     return response.newBuilder() 
       .body(ResponseBody.create(response.body().contentType(), bodyString)) 
       .build(); 
     //return response; 
    } 
} 

public static String bodyToString(final Request request) { 
    try { 
     final Request copy = request.newBuilder().build(); 
     final Buffer buffer = new Buffer(); 
     copy.body().writeTo(buffer); 
     return buffer.readUtf8(); 
    } catch (final IOException e) { 
     return "did not work"; 
    } 
}` 

Предоставлено: https://github.com/square/retrofit/issues/1072#

+0

, вы должны были упомянуть, что вы скопировали с https://github.com/square/retrofit/issues/1072# (чтобы отдать должное вашему источнику) – Gabor

+0

Это костыль, который нам больше не нужен. Вот пример рабочего журнала: http://stackoverflow.com/a/36847027/2557258 – Yazon2006

24

я встретил вещь, как вы и я попытался спросить у автора книги Дооснащения: Любовь работает с API, на Android (здесь это link) (Нету я не делаю несколько объявлений для них! ....но они действительно хорошие парни :) И автор ответил мне очень скоро, как с помощью метода Log на Retrofit 1.9, так и с Retrofit 2.0-beta.

А вот код Retrofit 2,0-бета:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
// set your desired log level 
logging.setLevel(Level.BODY); 

OkHttpClient httpClient = new OkHttpClient(); 
// add your other interceptors … 

// add logging as last interceptor 
httpClient.interceptors().add(logging); // <-- this is the important line! 

Retrofit retrofit = new Retrofit.Builder() 
    .baseUrl(API_BASE_URL) 
    .addConverterFactory(GsonConverterFactory.create()) 
    .client(httpClient) 
    .build(); 

Это как добавить метод протоколирования с помощью HttpLoggingInterceptor. Кроме того, если вы читаете эту книгу, о которой я упоминал выше, вы можете обнаружить, что она говорит, что больше не существует метода журнала с Retrofit 2.0 - что, я спросил у автора, неверно, и они будут обновлять книгу в следующем году об этом.

// Если вы не знакомы с методом «Журнал» в «Дооснащении», я хотел бы поделиться чем-то большим.

Также следует заметить, что есть некоторые уровни ведения журнала, которые вы могли бы выбрать. Я использую Level.BODY большую часть времени, что даст некоторые вещи, как это:

enter image description here

Вы можете найти почти все сотрудники HTTP внутри изображения: заголовок, содержание и ответ, и т. д.

А иногда вам действительно не нужны все гости для участия в вашей вечеринке: я просто хочу знать, успешно ли он подключен, что интернет-звонок успешно выполнен в моей Activiy & Fragmetn. Затем вы можете использовать Level.BASIC, который будет возвращать что-то вроде этого:

enter image description here

Вы можете найти код состояния 200 OK внутри? Вот и все :)

Также есть еще один, Level.HEADERS, который будет возвращать только заголовок сети. Я, конечно, еще одна картина здесь:

enter image description here

Это все Logging трюк;)

И я хотел бы поделиться с вами на уроке я узнал много there. У них есть куча замечательных сообщений о почти всем, что связано с Retrofit, и они продолжают обновлять почту, в то же время приближается Retrofit 2.0. Пожалуйста, взгляните на те работы, которые, я думаю, сэкономят вам много времени.

+0

Откуда возникает HttpLoggingInterceptor? – Radu

+4

Кроме того, это не работает для меня. httpClient.interceptors.add хочет com.squareup.okhttp.Interceptor, а не okhttp3.logging.HttpLoggingInterceptor – Radu

+0

@Radu Какая версия Модификации вы используете? У вашей градации должно быть что-то вроде этого: compile 'com.squareup.retrofit2: retrofit: 2.0.0-beta4' – peitek

3

Основная проблема, с которой я столкнулся, заключалась в динамическом добавлении заголовков и регистрации их в debug logcat. Я попытался добавить два перехватчика. Один для ведения журнала и один для добавления заголовков на ходу (авторизация токена). Проблема заключалась в том, что мы можем .addInterceptor или .addNetworkInterceptor. Как сказал мне Джейк Уортон: «Сетевые перехватчики всегда приходят после применения перехватчиков. См. https://github.com/square/okhttp/wiki/Interceptors».Так вот работает пример с заголовками и журналов:

OkHttpClient httpClient = new OkHttpClient.Builder() 
      //here we can add Interceptor for dynamical adding headers 
      .addNetworkInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Chain chain) throws IOException { 
        Request request = chain.request().newBuilder().addHeader("test", "test").build(); 
        return chain.proceed(request); 
       } 
      }) 
      //here we adding Interceptor for full level logging 
      .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) 
      .build(); 

    Retrofit retrofit = new Retrofit.Builder() 
      .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create())) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .client(httpClient) 
      .baseUrl(AppConstants.SERVER_ADDRESS) 
      .build(); 
2

Вы также можете добавить Stetho Facebook и смотреть на сети трасс в Chrome: http://facebook.github.io/stetho/

final OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
if (BuildConfig.DEBUG) { 
    builder.networkInterceptors().add(new StethoInterceptor()); 
} 

Затем откройте «хром: // инспектировать» в Chrome ...

0

Я нашел путь для печати Вход Модернизированный

OkHttpClient okHttpClient = new OkHttpClient.Builder() 
      .addInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Chain chain) throws IOException { 
        Request request = chain.request(); 
        if (BuildConfig.DEBUG) { 
         Log.e(getClass().getName(), request.method() + " " + request.url()); 
         Log.e(getClass().getName(), "" + request.header("Cookie")); 
         RequestBody rb = request.body(); 
         Buffer buffer = new Buffer(); 
         if (rb != null) 
          rb.writeTo(buffer); 
         LogUtils.LOGE(getClass().getName(), "Payload- " + buffer.readUtf8()); 
        } 
        return chain.proceed(request); 
       } 
      }) 
      .readTimeout(60, TimeUnit.SECONDS) 
      .connectTimeout(60, TimeUnit.SECONDS) 
      .build(); 

      iServices = new Retrofit.Builder() 
        .baseUrl("Your Base URL") 
        .client(okHttpClient) 
        .addConverterFactory(GsonConverterFactory.create()) 
        .build() 
        .create(Your Service Interface .class); 

Работает для меня.

4

Если вы используете 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))//first 
       .addInterceptor(new OAuthInterceptor(context))//second 
       .authenticator(new BearerTokenAuthenticator(context)) 
       .addInterceptor(loggingInterceptor)//third, log at the end 
       .build(); 
1

Лучший способ сделать это право на Модернизированный 2 является добавление регистратора перехватчик как networkInterceptor это будет распечатать сетевые заголовки и пользовательских заголовков слишком , Важно помнить, что перехватчик работает как стек и не забудьте добавить регистратор в конце всего.

OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
builder.addInterceptor(new MyCustomInterceptor()); 
builder.connectTimeout(60, TimeUnit.SECONDS); 
builder.readTimeout(60, TimeUnit.SECONDS); 
builder.writeTimeout(60, TimeUnit.SECONDS); 
// important line here 
builder.addNetworkInterceptor(LoggerInterceptor()); 
0

Большая часть ответов здесь охватывает почти все, кроме этого инструмента, одного из самых крутых способов увидеть журнал.

Это Facebook's Stetho. Это превосходный инструмент для мониторинга/регистрации сетевого трафика вашего приложения на google chrome. Вы также можете найти here на Github.

enter image description here

0

для Модернизированный 2.0.2 код как

**HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
     logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient.Builder httpClient=new OkHttpClient.Builder(); 
     httpClient.addInterceptor(logging);** 


     if (retrofit == null) { 
      retrofit = new Retrofit.Builder() 
        .baseUrl(BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create()) 
        **.client(httpClient.build())** 
        .build(); 
     } 
Смежные вопросы