Регистрация с помощью Retrofit 2

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

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(), которое мы использовали с Retrofit 1?

Ответ 1

В Retrofit 2 вы должны использовать HttpLoggingInterceptor.

Добавить зависимость к build.gradle. Последняя версия на октябрь 2019 года:

implementation 'com.squareup.okhttp3:logging-interceptor:4.2.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:

Старая версия Retrofit может потребовать более старой версии logging-interceptor. Посмотрите на разделы комментариев для деталей.

Ответ 2

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

И вот код Retrofit 2.0-beta:

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 - что, я спросил у автора, неверно, и они будут обновлять книгу в следующем году об этом.

//Если вы не знакомы с методом Log в Retrofit, я хотел бы поделиться чем-то большим.

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

введите описание изображения здесь

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

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

введите описание изображения здесь

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

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

введите описание изображения здесь

Что все трюки Logging;)

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

Ответ 3

Вот 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";
        }
    }
}

Ответ 4

Попробуйте следующее:

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

После этого в body находится интересующий вас JSON.

Ответ 5

Основная проблема, с которой я столкнулся, - это динамическое добавление заголовков и регистрация их в лог-код debug. Я попытался добавить два перехватчика. Один для ведения журнала и один для добавления заголовков на ходу (авторизация токена). Проблема заключалась в том, что мы можем .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();

Ответ 6

Я не знаю, вернет ли 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();

Ответ 7

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

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#

Ответ 8

Если вы используете 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();

Ответ 9

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

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

Затем откройте "chrome://inspect" в Chrome...

Ответ 10

Код Котлина

        val interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
        val retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build()

        return retrofit.create(PointApi::class.java)

Ответ 11

это создаст модифицированный объект с регистрацией. без создания отдельных объектов.

 private static final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(new OkHttpClient().newBuilder()
                    .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                    .readTimeout(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                    .writeTimeout(WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                    .connectTimeout(CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                    .build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

Ответ 12

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

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

Ответ 13

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

Это Facebook Stetho. Это превосходный инструмент для отслеживания/регистрации сетевого трафика вашего приложения на Google Chrome. Вы также можете найти здесь в Github.

введите описание изображения здесь

Ответ 14

для Retrofit 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();
        }

Ответ 15

Сначала добавьте зависимость в build.gradle:

реализация 'com.squareup.okhttp3: logging-interceptor: 3.12.1'

При использовании Kotlin вы можете добавить Logging Interceptor следующим образом:

companion object {
    val okHttpClient = OkHttpClient().newBuilder()
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
            .build()


    fun getRetrofitInstance(): Retrofit {
        val retrofit = Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(ScanNShopConstants.BASE_URL)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build()

        return retrofit
    }
}

Ответ 16

Я нашел способ для обновления журнала печати

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

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

Ответ 17

В котлин просто делай

class RetrofitFactory {
    companion object {
        fun getService(): ApiClient {

            val logging = HttpLoggingInterceptor()
            // set your desired log level
            logging.level = HttpLoggingInterceptor.Level.BODY

            val httpClient = OkHttpClient()
            // add interceptor
            httpClient.interceptors().add(logging)  // <-- this is the important line!

            val retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient)
                .build()

            return retrofit.create<ApiClient>(ApiClient::class.java)
        }

        const val BASE_URL = "https://yoururl.com/"
    }
}

Затем используйте RetrofitFactory.getService() чтобы получить экземпляр для модификации.

Ответ 18

Вот простой способ отфильтровать любые параметры запроса/ответа из журналов, используя HttpLoggingInterceptor:

// Request patterns to filter
private static final String[] REQUEST_PATTERNS = {
    "Content-Type",
};
// Response patterns to filter
private static final String[] RESPONSE_PATTERNS = {"Server", "server", "X-Powered-By", "Set-Cookie", "Expires", "Cache-Control", "Pragma", "Content-Length", "access-control-allow-origin"};

// Log requests and response
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
    @Override
    public void log(String message) {

        // Blacklist the elements not required
        for (String pattern: REQUEST_PATTERNS) {
            if (message.startsWith(pattern)) {
                return;
            }
        }
        // Any response patterns as well...
        for (String pattern: RESPONSE_PATTERNS) {
            if (message.startsWith(pattern)) {
                return;
            }
        }
        Log.d("RETROFIT", message);
    }
});
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

Вот полная суть:

https://gist.github.com/mankum93/179c2d5378f27e95742c3f2434de7168

Ответ 19

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

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