Регистрация с помощью 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);
}