Come registrare la richiesta e il corpo della risposta con Retrofit-Android?


129

Non riesco a trovare metodi pertinenti nell'API Retrofit per la registrazione di corpi di richiesta / risposta completi. Mi aspettavo un aiuto nel Profiler (ma offre solo metadati sulla risposta). Ho provato a impostare il livello di log nel Builder, ma neanche questo mi aiuta:

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

EDIT: questo codice ora funziona. Non so perché prima non funzionasse. Forse perché stavo usando una versione precedente del retrofit.


L'hai mai capito? La documentazione dice che FULLdovrebbe dare il corpo ma non sembra.
theblang

1
@ mattblang: non so cosa fosse successo prima, ma questo codice ora funziona.
Jaguar

Possibile duplicato della registrazione con Retrofit 2
bryant1410


Probabilmente la corsa istantanea si sarebbe incasinata se non avesse funzionato prima
deathangel908

Risposte:


91

Ho usato setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), mi ha aiutato.
AGGIORNARE.
Puoi anche provare a utilizzare a scopo di debug retrofit.client.Responsecome modello di risposta


2
AndroidLog, che classe è quella?
theblang

Viene fornito con la libreria Retrofit.
Alex Dzeshko

2
Vedo. Sfortunatamente questo non ti dà il response body, anche se nel documento è indicato che LogLevel.FULL dovrebbe darti il response body.
theblang

Questo può essere visto con "YOUR_LOG_TAG" nel logcat di Android nella scheda dettagliata.
rajeesh

4
LogLevel.Full non esiste in retrofit 2

121

Retrofit 2.0 :

AGGIORNAMENTO: @ di Marcus Pöhls

Accesso all'aggiornamento 2

Retrofit 2 si basa completamente su OkHttp per qualsiasi operazione di rete. Poiché OkHttp è una dipendenza peer di Retrofit 2, non sarà necessario aggiungere una dipendenza aggiuntiva una volta che Retrofit 2 viene rilasciato come versione stabile.

OkHttp 2.6.0 viene fornito con un intercettore di registrazione come dipendenza interna e puoi usarlo direttamente per il tuo client Retrofit. Retrofit 2.0.0-beta2 utilizza ancora OkHttp 2.5.0. Le versioni future aumenteranno la dipendenza a versioni OkHttp superiori. Ecco perché è necessario importare manualmente l'intercettore di registrazione. Aggiungi la seguente riga alle tue importazioni gradle all'interno del tuo file build.gradle per recuperare la dipendenza dell'interceptor di registrazione.

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

Puoi anche visitare la pagina GitHub di Square su questo intercettore

Aggiungi registrazione al retrofit 2

Durante lo sviluppo della tua app e per scopi di debug è utile avere una funzionalità di registro integrata per mostrare le informazioni sulla richiesta e sulla risposta. Poiché la registrazione non è più integrata per impostazione predefinita in Retrofit 2, è necessario aggiungere un intercettore della registrazione per OkHttp. Fortunatamente OkHttp viene già fornito con questo intercettore e devi solo attivarlo per il tuo 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();

Ti consigliamo di aggiungere la registrazione come ultimo intercettore, perché questo registrerà anche le informazioni che hai aggiunto con gli intercettatori precedenti alla tua richiesta.

Livelli di registro

La registrazione di troppe informazioni farà saltare in aria il tuo monitor Android, ecco perché l'interceptor di registrazione di OkHttp ha quattro livelli di log: NONE, BASIC, HEADERS, BODY. Ti guideremo attraverso ciascuno dei livelli di registro e descriveremo il loro output.

ulteriori informazioni, visitare: Retrofit 2 - Richieste di registro e risposte

VECCHIA RISPOSTA:

nessun accesso a Retrofit 2 più. Il team di sviluppo ha rimosso la funzionalità di registrazione. Ad essere onesti, la funzione di registrazione non era comunque così affidabile. Jake Wharton ha dichiarato esplicitamente che i messaggi o gli oggetti registrati sono i valori presunti e non è stato possibile provare che siano veri. La richiesta effettiva che arriva al server potrebbe avere un corpo della richiesta modificato o qualcos'altro.

Anche se non esiste un logging integrato per impostazione predefinita, puoi sfruttare qualsiasi logger Java e utilizzarlo all'interno di un intercettore OkHttp personalizzato.

Per ulteriori informazioni su Retrofit 2, fare riferimento a: Retrofit - Guida introduttiva e creazione di un client Android


1
C'è anche un post specifico per l'accesso a Retrofit 2.0: futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek

Ottimo modo per rendere tutto più complicato di quanto dovrebbe essere. Mi ricorda la registrazione di Jersey 1 vs Jersey 2. Più codice boilerplate ...
breakline

L'aggiunta di intercettori in questo modo ora si tradurrà in un'eccezione UnsupportedOperationException in OkHttp v3. Il nuovo modo è: OkHttpClient.Builder (). AddInterceptor (logging) .build () github.com/square/okhttp/issues/2219
Amagi82

@JawadLeWywadi sì, usando questo codice puoi stampare il corpo
Dhaval Jivani

Per Retrofit 2, questo è molto più semplice.
Gary99

31

Aggiornamento per Retrofit 2.0.0-beta3

Ora devi usare okhttp3 con builder. Anche il vecchio intercettore non funzionerà. Questa risposta è su misura per Android.

Ecco una rapida copia incolla per te con le nuove cose.

1. Modifica il tuo file gradle in

  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. Controlla questo codice di esempio:

con le nuove importazioni. Puoi rimuovere Rx se non lo usi, rimuovi anche ciò che non usi.

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

indennità

So che è offtopico ma lo trovo interessante.

Nel caso in cui ci sia un codice di errore http di non autorizzato , ecco un intercettore. Uso Eventbus per trasmettere l'evento.

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

codice preso da https://github.com/AndreiD/UltimateAndroidTemplateRx (il mio progetto).


9

Non sembra esserci un modo per fare basic + body, ma puoi usare FULL e filtrare le intestazioni che non vuoi.

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

Sembra che quando si sovrascrive il log, il corpo è preceduto da un tag simile a

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

quindi dovrebbe essere facile registrare basic + body regolando il filtro personalizzato. Sto usando una lista nera, ma potrebbe essere utilizzata anche una lista bianca a seconda delle tue esigenze.


4

sotto il codice funziona sia con l'intestazione che senza intestazione per stampare la richiesta e la risposta del registro. Nota: basta commentare la riga .addHeader () se non si utilizza l'intestazione.

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

Spero che questo codice ti aiuti ad accedere.
devi solo aggiungere l'interceptor nel tuo Build.Gradlethen make RetrofitClient.

Primo passo

Aggiungi questa riga al tuo file build.gradle

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

Secondo passo

Crea il tuo cliente di retrofit


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

chiamata

RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 

2

Se stai usando Retrofit2 e okhttp3 allora devi sapere che Interceptor funziona in coda. Quindi aggiungi loggingInterceptor alla fine, dopo gli altri tuoi 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))
                .addInterceptor(new OAuthInterceptor(context))
                .authenticator(new BearerTokenAuthenticator(context))
                .addInterceptor(loggingInterceptor)//at the end
                .build();


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.