Registrazione con Retrofit 2

Sto cercando di ottenere il JSON esatto che viene inviato nella richiesta. Ecco il mio codice:

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

Ma vedo solo questo nei registri:

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

Come dovrei fare il logging corretto, data la rimozione di setLog() e setLogLevel() che setLogLevel() con Retrofit 1?

In Retrofit 2 è necessario utilizzare HttpLoggingInterceptor .

Aggiungi dipendenza a build.gradle :

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

Creare un object Retrofit come il seguente:

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

La soluzione di cui sopra ti dà messaggi logcat molto simili a quelli vecchi impostati da

 setLogLevel(RestAdapter.LogLevel.FULL) 

In caso di java.lang.ClassNotFoundException :

La versione Retrofit precedente potrebbe richiedere una versione precedente logging-interceptor . Dai un’occhiata alle sezioni dei commenti per i dettagli.

Ho incontrato la cosa come te e ho provato a chiedere all’autore del libro Retrofit: Amore che lavora con le API su Android (ecco il link ) (no! Non sto facendo alcuni annunci per loro … ma sono davvero carini ragazzi 🙂 E l’autore mi ha risposto molto presto, con entrambi i metodi Log su Retrofit 1.9 e Retrofit 2.0-beta.

Ed ecco il codice di 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(); 

Ecco come aggiungere il metodo di registrazione con l'aiuto di HttpLoggingInterceptor . Anche se sei il lettore di quel libro che ho menzionato sopra, potresti scoprire che non esiste più il metodo log con Retrofit 2.0 - che, avevo chiesto all'autore, non è corretto e aggiorneranno il libro l'anno prossimo parlando a proposito.

// Nel caso in cui non si abbia familiarità con il metodo Log in Retrofit, mi piacerebbe condividere qualcosa di più.

Si noti inoltre che ci sono alcuni livelli di registrazione che è ansible selezionare. Io uso il Level.BODY la maggior parte delle volte, il che darà qualcosa del genere:

inserisci la descrizione dell'immagine qui

Puoi trovare quasi tutto il personale http all'interno dell'immagine: l'intestazione, il contenuto e la risposta, ecc.

E a volte davvero non hai bisogno che tutti gli ospiti partecipino alla tua festa: voglio solo sapere se è connesso con successo, che la chiamata via Internet è stata effettuata con successo all'interno della mia Activiy & Fragmetn. Allora sei libero di usare Level.BASIC , che restituirà qualcosa di simile a questo:

inserisci la descrizione dell'immagine qui

Riesci a trovare il codice di stato 200 OK all'interno? Questo è 🙂

Inoltre ce n'è un altro, Level.HEADERS , che restituirà solo l'intestazione della rete. Ya ovviamente un'altra immagine qui:

inserisci la descrizione dell'immagine qui

Questo è tutto il trucco di registrazione;)

E mi piacerebbe condividerti con il tutorial che ho imparato molto lì . Hanno un bel po 'di post parlando di quasi tutto ciò che riguarda il Retrofit, e stanno continuando ad aggiornare il post, allo stesso tempo sta arrivando il Retrofit 2.0. Per favore, date un'occhiata a quei lavori, che penso ti risparmieranno un sacco di tempo.

Ecco un Interceptor che registra sia i corpi di richiesta che di risposta (usando Timber, basato su un esempio dei documenti di OkHttp e alcune altre risposte di 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"; } } } 

Prova questo:

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

Dopo questo, nel body c’è il JSON a cui sei interessato.

Non so se setLogLevel () ritornerà nella versione 2.0 finale di Retrofit ma per ora puoi usare un intercettore per la registrazione.

Un buon esempio può essere trovato nella wiki di 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(); 

Per coloro che necessitano di registrazione di alto livello in Retrofit, utilizzare l’intercettore come questo

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

Per gentile concessione : https://github.com/square/retrofit/issues/1072#

Il problema principale che ho dovuto affrontare è stato aggiungere delle intestazioni dinamiche e registrarle in debug logcat. Ho provato ad aggiungere due intercettori. Uno per la registrazione e uno per aggiungere intestazioni on-the-go (authorization token). Il problema era che potremmo .addInterceptor o .addNetworkInterceptor. Come mi ha detto Jake Wharton: “Gli intercettori di rete arrivano sempre dopo intercettatori di applicazioni. Vedi https://github.com/square/okhttp/wiki/Interceptors “. Quindi ecco un esempio funzionante con intestazioni e registri:

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

Se si utilizza Retrofit2 e okhttp3, è necessario sapere che Interceptor funziona in base alla coda. Quindi aggiungi loggingInterceptor alla fine, dopo gli altri Interceptor:

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

Puoi anche aggiungere Stetho di Facebook e guardare le tracce di rete in Chrome: http://facebook.github.io/stetho/

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

Quindi apri “chrome: // inspect” in Chrome …

Un modo migliore per farlo correttamente in Retrofit 2 è aggiungere l’intercettore del logger come networkInterceptor per stampare anche le intestazioni di rete e le intestazioni personalizzate. L’importante è ricordare che l’intercettatore funziona come uno stack e sii sicuro di aggiungere il logger alla fine di tutto.

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

Ho trovato il modo di stampare il log in Retrofit

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

Per me va bene.

La maggior parte della risposta qui copre quasi tutto tranne questo strumento, uno dei modi più interessanti per vedere il registro.

È Stetho di Facebook . Questo è lo strumento eccezionale per monitorare / registrare il traffico di rete della tua app su google chrome . Puoi anche trovarlo qui su Github.

inserisci la descrizione dell'immagine qui

per Retrofit 2.0.2 il codice è come

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

Codice Kotlin

  val interceptor = HttpLoggingInterceptor() interceptor.setLevel(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) 

hey ragazzi, ho già trovato una soluzione:

  public static  T createApi(Context context, Class 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); }