Retrofit-Android ile istek ve yanıt kuruluşu nasıl kaydedilir?


129

Eksiksiz istek / yanıt gövdelerini günlüğe kaydetmek için Retrofit API'de ilgili yöntemler bulamıyorum. Profiler'da biraz yardım bekliyordum (ancak yalnızca yanıtla ilgili meta veriler sunuyor). Builder'da günlük düzeyini ayarlamayı denedim, ancak bu da bana yardımcı olmuyor:

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

DÜZENLEME: Bu kod şimdi çalışıyor. Neden daha önce işe yaramadığını bilmiyorum. Muhtemelen eski bir güçlendirme versiyonunu kullandığım için.


Bunu hiç çözdün mü? Belgeler bunun FULLbedeni vermesi gerektiğini söylüyor ama öyle görünmüyor.
theblang

1
@mattblang: Daha önce neyin yanlış olduğunu bilmiyorum ama bu kod şimdi çalışıyor.
Jaguar



Muhtemelen anlık çalıştırma daha önce işe yaramadıysa
berbattı

Yanıtlar:


91

Kullandım setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), bana yardımcı oldu.
GÜNCELLEME.
Ayrıca retrofit.client.Responseyanıt modeli olarak hata ayıklama amaçlı kullanmayı da deneyebilirsiniz.


2
AndroidLog, bu hangi sınıf?
theblang

Retrofit kitaplığı ile birlikte gelir.
Alex Dzeshko

2
Anlıyorum. Ne yazık ki bu sana vermez response bodyo doc devleti yapar rağmen LogLevel.FULL gerektiğini size response body.
theblang

Bu, ayrıntılı sekme altında android logcat'te "YOUR_LOG_TAG" ile görülebilir.
rajeesh

4
LogLevel.Full, retrofit 2'de mevcut değil

121

İyileştirme 2.0 :

GÜNCELLEME: @ Marcus Pöhls

Güçlendirme 2 Oturum Açma

Retrofit 2, herhangi bir ağ çalışması için tamamen OkHttp'ye güvenir. OkHttp, Retrofit 2'nin eş bağımlılığı olduğundan, Retrofit 2 kararlı bir sürüm olarak piyasaya sürüldüğünde ek bir bağımlılık eklemenize gerek yoktur.

OkHttp 2.6.0, dahili bağımlılık olarak bir günlük durdurucu ile birlikte gelir ve onu Retrofit istemciniz için doğrudan kullanabilirsiniz. Retrofit 2.0.0-beta2 hala OkHttp 2.5.0 kullanıyor. Gelecek sürümler, bağımlılığı daha yüksek OkHttp sürümlerine yükseltecektir. Bu nedenle, günlük yakalayıcıyı manuel olarak içe aktarmanız gerekir. Logging interceptor bağımlılığını getirmek için build.gradle dosyanızdaki gradle içe aktarmalarınıza aşağıdaki satırı ekleyin.

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

Bu engelleyici hakkında Square'in GitHub sayfasını da ziyaret edebilirsiniz.

Güçlendirme 2'ye Günlük Kaydı Ekle

Uygulamanızı geliştirirken ve hata ayıklama amacıyla, istek ve yanıt bilgilerini göstermek için entegre bir günlük özelliğine sahip olmak güzel. Retrofit 2'de artık günlük kaydı varsayılan olarak entegre olmadığından, OkHttp için bir günlük durdurucu eklememiz gerekiyor. Neyse ki OkHttp zaten bu önleyiciyle birlikte geliyor ve sadece OkHttpClient'iniz için etkinleştirmeniz gerekiyor.

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

Son engelleyici olarak günlüğe kaydetmeyi eklemenizi öneririz, çünkü bu aynı zamanda talebinize önceki engelleyicilerle eklediğiniz bilgileri de günlüğe kaydedecektir.

Günlük Seviyeleri

Çok fazla bilginin günlüğe kaydedilmesi Android monitörünüzü havaya uçuracaktır, bu yüzden OkHttp'nin günlüğe kaydetme engelleyicisinin dört günlük seviyesi vardır: HİÇBİRİ, TEMEL, BAŞLIKLAR, GÖVDE. Günlük düzeylerinin her birinde size yol göstereceğiz ve çıktılarını açıklayacağız.

daha fazla bilgi için lütfen şu adresi ziyaret edin: Güçlendirme 2 - Günlük İstekleri ve Yanıtları

ESKİ CEVAP:

Artık Retrofit 2'de oturum açmak yok. Geliştirme ekibi günlük kaydı özelliğini kaldırdı. Dürüst olmak gerekirse, günlük kaydı özelliği o kadar da güvenilir değildi. Jake Wharton, günlüğe kaydedilen mesajların veya nesnelerin varsayılan değerler olduğunu ve doğru olduklarının kanıtlanamayacağını açıkça belirtti. Sunucuya ulaşan asıl isteğin değiştirilmiş bir istek gövdesi veya başka bir şey olabilir.

Varsayılan olarak entegre bir günlük kaydı olmasa bile, herhangi bir Java kaydediciden yararlanabilir ve bunu özelleştirilmiş bir OkHttp engelleyici içinde kullanabilirsiniz.

Retrofit 2 hakkında daha fazla bilgi için lütfen bakınız: Retrofit - Başlarken ve Bir Android İstemcisi Oluşturun


1
Recommended 2.0 oyuna giriş yaparak Yayın belirli de vardır: futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek

Her şeyi olması gerekenden daha karmaşık hale getirmenin harika bir yolu. Bana Jersey 1 vs Jersey 2 günlüklerini hatırlatıyor. Daha fazla standart kod ....
kesme satırı

Bu şekilde engelleyiciler eklemek artık OkHttp v3'te bir UnsupportedOperationException ile sonuçlanacaktır. Yeni yol: OkHttpClient.Builder (). AddInterceptor (günlük kaydı) .build () github.com/square/okhttp/issues/2219
Amagi82

@JawadLeWywadi evet bu kodu kullanarak gövde yazdırabilirsiniz
Dhaval Jivani

Retrofit 2 için bu çok daha kolaydır.
Gary99

31

Retrofit 2.0.0-beta3 güncellemesi

Şimdi builder ile okhttp3'ü kullanmalısınız. Ayrıca eski durdurucu çalışmayacaktır. Bu yanıt Android için uyarlanmıştır.

İşte size yeni malzemelerle hızlı bir kopyala yapıştır.

1. Not defteri dosyanızı şu şekilde değiştirin:

  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. Bu örnek kodu kontrol edin:

yeni ithalatlar ile. Kullanmazsanız Rx'i kaldırabilirsiniz, kullanmadıklarınızı da kaldırabilirsiniz.

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

Bonus

Offtopik olduğunu biliyorum ama havalı buluyorum.

Yetkisiz bir http hata kodu olması durumunda , burada bir durdurucu var. Olayı iletmek için olay veri yolu kullanıyorum.

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

kod https://github.com/AndreiD/UltimateAndroidTemplateRx (projem) adresinden alınır .


9

Temel + gövde yapmanın bir yolu yok gibi görünüyor, ancak FULL kullanabilir ve istemediğiniz başlıkları filtreleyebilirsiniz.

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

Günlüğü geçersiz kılarken, gövdeye benzer bir etiketin öneki olduğu görülüyor.

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

bu nedenle, özel filtreyi ayarlayarak temel + gövde günlüğünü kaydetmek kolay olmalıdır. Kara liste kullanıyorum, ancak ihtiyaçlarınıza bağlı olarak bir beyaz liste de kullanılabilir.


4

Aşağıdaki kod, günlük isteği ve yanıtını yazdırmak için hem başlık hem de başlık olmadan çalışıyor. Not: Başlık kullanmıyorsanız .addHeader () satırına yorum yapmanız yeterlidir.

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

Umarım bu kod oturum açmanıza yardımcı olur.
Eğer sadece içinde önleme eklemeniz gerekir Build.Gradlesonra marka RetrofitClient.

İlk adım

Bu satırı build.gradle

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

İkinci adım

Retrofit Müşterinizi yapın


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

çağrı

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

2

Retrofit2 ve okhttp3 kullanıyorsanız, Interceptor'ın kuyruğa göre çalıştığını bilmeniz gerekir. Bu nedenle, diğer Interceptor'larınızdan sonra loggingInterceptor'ı sonuna ekleyin:

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


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.