How to log request and response body with Retrofit-Android?
我在Retrofit API中找不到用于记录完整的请求/响应正文的相关方法。 一世
在Profiler中期待一些帮助(但它仅提供有关响应的元数据)。 我尝试在Builder中设置日志级别,但这也无济于事:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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(); |
编辑:此代码现在正在工作。 我不知道为什么它不起作用。 可能是因为我使用的是旧版本的改造。
改造2.0:
更新:@by Marcus P?hls
登录改造2
Retrofit 2完全依赖OkHttp进行任何网络操作。由于OkHttp是Retrofit 2的对等依赖项,因此,在Retrofit 2作为稳定版本发布后,您无需添加其他依赖项。
OkHttp 2.6.0附带日志拦截器作为内部依赖项,您可以将其直接用于Retrofit客户端。改造2.0.0-beta2仍使用OkHttp 2.5.0。将来的发行版将使对更高的OkHttp版本的依赖性增加。因此,您需要手动导入日志记录拦截器。将以下行添加到build.gradle文件中的gradle导入中,以获取日志记录拦截器依赖项。
1 | compile 'com.squareup.okhttp3:logging-interceptor:3.9.0' |
您还可以访问Square的有关此拦截器的GitHub页面
将日志记录添加到改造2
在开发应用程序和进行调试时,最好集成日志功能以显示请求和响应信息。由于Retrofit 2中不再默认集成日志记录,因此我们需要为OkHttp添加日志记录拦截器。幸运的是,OkHttp已经附带了此拦截器,您只需要为OkHttpClient激活它即可。
1 2 3 4 5 6 7 8 9 10 11 12 | 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(); |
我们建议将日志记录添加为最后一个拦截器,因为这还将记录您与以前的拦截器一起添加到您的请求中的信息。
日志级别
记录太多信息将使您的Android显示器崩溃,这就是OkHttp的记录拦截器具有四个日志级别的原因:NONE,BASIC,HEADERS,BODY。我们将引导您遍历每个日志级别并描述其输出。
更多信息,请访问:改造2-日志请求和响应
旧答案:
不再登录Retrofit 2。开发团队删除了日志记录功能。老实说,日志记录功能并不是那么可靠。杰克·沃顿(Jake Wharton)明确表示,记录的消息或对象是假定的值,无法证明它们是真实的。到达服务器的实际请求可能具有更改的请求正文或其他内容。
即使默认情况下没有集成日志记录,您也可以利用任何Java记录器并在自定义的OkHttp拦截器中使用它。
有关翻新2的更多信息,请参考:
改造-入门和创建Android客户端
我使用了
更新。您也可以尝试将
Retrofit 2.0.0-beta3的更新
现在,您必须将okhttp3与builder一起使用。同样,旧的拦截器将无法工作。此响应是针对Android量身定制的。
这是为您提供新内容的快速复制粘贴。
1.将gradle文件修改为
1 2 3 4 | 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.检查以下示例代码:
与新的进口。您可以删除不使用的Rx,也可以删除不使用的Rx。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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); } } } |
奖金
我知道这是题外话,但我觉得它很酷。
如果有未经授权的http错误代码,这里是一个拦截器。我使用事件总线来传输事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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; } } |
代码来自https://github.com/AndreiD/UltimateAndroidTemplateRx(我的项目)。
似乎没有一种执行基本+正文的方法,但是您可以使用FULL并过滤不需要的标头。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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(); |
似乎在覆盖日志时,主体的前缀类似于
1 | [ 02-25 10:42:30.317 25645:26335 D/Retrofit ] |
因此通过调整自定义过滤器,可以轻松记录基本+正文。我正在使用黑名单,但是根据您的需要也可以使用白名单。
下面的代码适用于带头和不带头的情况,以打印日志请求和响应。注意:如果不使用标头,则只需注释.addHeader()行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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(); |
我希望这段代码可以帮助您登录。
您只需要在
第一步
将此行添加到您的
1 | implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' |
第二步
使您的改造客户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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; } } |
呼唤
1 | RetrofitClient.getInstance(context).getApiService().yourRequestCall(); |
如果您正在使用Retrofit2和okhttp3,则需要知道Interceptor按队列工作。因此,在其他拦截器之后,最后添加loggingInterceptor:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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(); |
ZoomX-Android Logger拦截器是一款出色的拦截器,可以帮助您解决问题。
适用于3.0之前的android studio(使用android motinor)
https://futurestud.io/tutorials/retrofit-2-log-requests-and-responses
对于3.0及以上版本的android studio(使用android profiler作为android monitor替换为android profiler)
https://futurestud.io/tutorials/retrofit-2-analyze-network-traffic-with-android-studio-profiler