web-dev-qa-db-fra.com

Enregistrement avec Retrofit 2

J'essaie d'obtenir le code JSON exact qui est envoyé dans la demande. Voici mon code:

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

Mais je ne vois cela que dans les journaux:

request:
com.squareup.okhttp.RequestBody$1@3ff4074d
headers:
Content-Type: application/vnd.ll.event.list+json

Comment suis-je censé faire une journalisation correcte, étant donné le retrait de setLog() et setLogLevel() que nous avions l'habitude d'utiliser avec Retrofit 1?

279
Gabor

Dans Retrofit 2, vous devez utiliser HttpLoggingInterceptor .

Ajouter une dépendance à build.gradle:

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

Créez un objet Retrofit comme suit:

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 solution ci-dessus vous donne des messages logcat très similaires aux anciens définis par

setLogLevel(RestAdapter.LogLevel.FULL)

Dans le cas de Java.lang.ClassNotFoundException:

Une version plus ancienne de Retrofit peut nécessiter une version plus ancienne de logging-interceptor. Consultez les sections de commentaires pour plus de détails.

628
klimat

J'ai rencontré la chose alors que vous essayiez de demander à l'auteur du livre (= /// =): adore travailler avec des API sur Android (voici le lien ) (non! je ne fais pas de publicité pour eux .... mais ce sont vraiment des gars sympas :) Et l'auteur m'a répondu très bientôt, avec les deux méthodes Log sur Retrofit 1.9 et Retrofit 2.0-beta.

Et voici le code de 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();

Voici comment ajouter une méthode de journalisation à l’aide de HttpLoggingInterceptor . De plus, si vous êtes le lecteur de ce livre que j'ai mentionné ci-dessus, vous constaterez peut-être qu'il n'y a plus de méthode de journalisation avec Retrofit 2.0 - ce que, j'avais demandé à l'auteur, n'est pas correct et ils mettront à jour le livre l'année prochaine. à propos de ça.

// Si vous n'êtes pas familiarisé avec la méthode Log dans Retrofit, j'aimerais partager quelque chose de plus.

Il convient également de noter qu’il existe certains niveaux de journalisation que vous pouvez choisir. J'utilise le Level.BODY la plupart du temps, ce qui donnera une chose comme ceci:

enter image description here

Vous pouvez trouver presque tout le personnel http dans l'image: l'en-tête, le contenu et la réponse, etc.

Et parfois, vous n'avez vraiment pas besoin de tous les invités pour assister à votre fête: je veux juste savoir si la connexion est établie avec succès, cet appel Internet est passé avec succès dans mon Activiy & Fragmetn. Ensuite, vous êtes libre d'utiliser Level.BASIC , ce qui retournera quelque chose comme ceci:

enter image description here

Pouvez-vous trouver le code d'état 200 OK à l'intérieur? C'est ça :)

Il y a aussi un autre, Level.HEADERS , qui ne renverra que l'en-tête du réseau. Ya bien sur une autre photo ici:

enter image description here

C'est tout le truc de la journalisation;)

Et je voudrais vous partager avec le tutoriel, j'ai beaucoup appris . Ils ont énormément de bons articles qui parlent de presque tout ce qui concerne Retrofit, et ils continuent à le mettre à jour, alors que Retrofit 2.0 arrive. Veuillez jeter un coup d'œil à ces travaux qui, je pense, vous feront gagner beaucoup de temps.

30
Anthonyeef

Voici un Interceptor qui enregistre les corps de la demande et de la réponse (à l'aide de Timber, basé sur un exemple tiré de la documentation OkHttp et de quelques autres réponses 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";
        }
    }
}
10
david.mihola

Essaye ça:

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

Ensuite, dans la body, vous trouverez le JSON qui vous intéresse.

6
Anton Ryabyh

Je ne sais pas si setLogLevel () reviendra dans la version 2.0 finale de Retrofit, mais pour l'instant, vous pouvez utiliser un intercepteur pour la journalisation.

Un bon exemple peut être trouvé dans le wiki 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();
4
oceanfeeling

Si vous utilisez Retrofit2 et okhttp3, vous devez savoir qu'Interceptor fonctionne par file d'attente. Ajoutez donc loggingInterceptor à la fin, après vos autres Interceptors:

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

Le problème principal auquel j’ai été confronté était l’ajout dynamique d’en-têtes et leur connexion à Debug Logcat. J'ai essayé d'ajouter deux intercepteurs. Un pour la journalisation et un pour l'ajout d'en-têtes à la volée (autorisation de jeton). Le problème était que nous pouvons .addInterceptor ou .addNetworkInterceptor. Comme Jake Wharton m'a dit: "Les intercepteurs de réseau viennent toujours après les intercepteurs d'applications. Voir https://github.com/square/okhttp/wiki/Interceptors ". Voici donc un exemple de travail avec les en-têtes et les journaux:

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

Pour ceux qui ont besoin d’une connexion de haut niveau dans Retrofit, utilisez l’intercepteur comme celui-ci.

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

Courtoisie : https://github.com/square/retrofit/issues/1072#

4
DGN

Code Kotlin

        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)
2
Jorge Casariego

Vous pouvez également ajouter le Stetho de Facebook et consulter les traces du réseau dans Chrome: http://facebook.github.io/stetho/

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

Puis ouvrez "chrome: // inspect" dans Chrome ...

2
kenyee

cela créera un objet de modification avec la journalisation. sans créer des objets séparés.

 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();
2
Jay Dangar

La plupart de la réponse ici couvre presque tout sauf cet outil, l'un des moyens les plus cool de voir le journal.

C'est Stetho de Facebook . C’est le meilleur outil pour surveiller/enregistrer le trafic réseau de votre application sur Google Chrome . Vous pouvez également trouver ici sur Github.

enter image description here

1
Nishant Shah

Ajoutez d'abord la dépendance à build.gradle:

implémentation 'com.squareup.okhttp3: logging-interceptor: 3.12.1'

En utilisant Kotlin, vous pouvez ajouter Logging Interceptor comme ceci:

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
    }
}
1
Vinay John

pour Retrofit 2.0.2 le code est comme

   **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();
        }
1
other Tall guy

Une meilleure façon de procéder correctement dans Retrofit 2 consiste à ajouter l’intercepteur d’enregistreur en tant qu’interface réseau, ce qui permettra également d’imprimer les en-têtes de réseau et vos en-têtes personnalisés. L'important est de se rappeler que l'intercepteur fonctionne comme une pile et de s'assurer que vous ajoutez l'enregistreur à la fin.

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

ZoomX - Android Logger Interceptor Tool est un excellent intercepteur Android pour Retrofit 2

0
Ibrahim AbdelGawad

Voici un moyen simple de filtrer tous les paramètres de requête/réponse des journaux en utilisant 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);

Voici le résumé complet:

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

0
pulp_fiction

J'ai trouvé le moyen d'imprimer la connexion dans la modernisation

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

Travaille pour moi.

0
Nilesh Senta