logging与改造2
我正在尝试获取请求中正在发送的确切的JSON。 这是我的代码:
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();
但是我只在日志中看到这个:
request: com.squareup.okhttp.RequestBody$1@3ff4074d headers: Content-Type: application/vnd.ll.event.list+json
我该如何做适当的日志logging,因为删除了我们用于Retrofit 1的setLog()
和setLogLevel()
?
在Retrofit 2中,你应该使用HttpLoggingInterceptor 。
添加依赖到build.gradle
:
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
创buildRetrofit
对象,如下所示:
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);
上面的解决scheme给你logcat日志非常类似于旧的设置
setLogLevel(RestAdapter.LogLevel.FULL)
更新2.1.0更新:
使用拦截器v3.3.1,否则你会得到以下错误 – java.lang.NoSuchMethodError: No virtual method log(Ljava/lang/String;)V in class Lokhttp3/internal/Platform; or its super classes
java.lang.NoSuchMethodError: No virtual method log(Ljava/lang/String;)V in class Lokhttp3/internal/Platform; or its super classes
2.1.0的configuration如下所示:
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
对于Retrofit 2.3.0,使用3.6.0拦截器(在早期版本中会出现各种错误)。
我遇到了你的事情,我试着问这本书的作者Retrofit:爱在Android上使用API (这里是链接 )(不,我不是为他们做一些广告….但他们真的很好家伙:)作者很快回复了我,同时在Retrofit 1.9和Retrofit 2.0-beta上都使用了Log方法。
以下是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();
这是如何添加日志logging方法的帮助下HttpLoggingInterceptor 。 另外,如果你是我上面提到的那本书的读者,你可能会发现它已经不再使用Retrofit 2.0的日志方法 – 我曾问过作者,这是不正确的,他们将在明年更新这本书关于它。
//如果您对Retrofit中的Log方法不太熟悉,我想分享一些更多内容。
还应该注意到有一些日志级别可以select。 大部分时间我都使用Level.BODY ,这会给出一些这样的事情:
你可以在图片里find几乎所有的http工作人员:标题,内容和回应等等。
有时你并不需要所有的客人参加你的派对:我只是想知道它是否成功连接,在我的Activiy&Fragmetnnetworking电话成功。 那么你可以自由使用Level.BASIC ,它将返回如下所示的内容:
你能在里面find状态码200 OK吗? 这就对了 :)
另外还有一个Level.HEADERS ,它只返回networking的头部。 当然雅另一张图片在这里:
这就是所有的Logging技巧;)
我想和大家分享一下我在那里学到的教程。 他们有一大堆好post,谈论几乎与改造有关的所有事情,他们正在不断更新post,同时Retrofit 2.0即将到来。 请看看这些工作,我认为这会为您节省大量的时间。
这里是一个Interceptor
,它logging了请求和响应主体(使用Timber,基于OkHttp文档中的一个例子以及其他的一些答案):
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"; } } }
尝试这个:
Request request = chain.request(); Buffer buffer = new Buffer(); request.body().writeTo(buffer); String body = buffer.readUtf8();
在此之后,在body
有你感兴趣的JSON。
我不知道如果setLogLevel()将在最终的2.0版本的Retrofit中返回,但现在你可以使用拦截器进行日志logging。
一个很好的例子可以在OkHttp wiki中find: 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();
对于那些需要在Retrofit中进行高级日志logging的人,就像这样使用拦截器
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"; } }`
礼貌 : https : //github.com/square/retrofit/issues/1072#
如果你正在使用Retrofit2和okhttp3,那么你需要知道拦截器是按队列工作的。 所以在你的其他拦截器之后添加loggingInterceptor:
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();
我面临的主要问题是dynamic添加标题并将其logging到debugginglogcat中。 我试图添加两个拦截器。 一个用于日志logging,另一个用于在移动中添加标题(令牌授权)。 问题是我们可能.addInterceptor或.addNetworkInterceptor。 正如杰克·沃顿(Jake Wharton)对我说:“networking拦截器总是在应用程序拦截器之后出现,请参阅https://github.com/square/okhttp/wiki/Interceptors 。 所以这里是工作示例与标题和日志:
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();
您还可以添加Facebook的Stetho并查看Chrome中的networking痕迹: http ://facebook.github.io/stetho/
final OkHttpClient.Builder builder = new OkHttpClient.Builder(); if (BuildConfig.DEBUG) { builder.networkInterceptors().add(new StethoInterceptor()); }
然后在Chrome中打开“chrome:// inspect”…
在Retrofit 2中这样做的最好方法是将logging器拦截器添加为networkInterceptor,这将打印出networking标题和自定义标题。 重要的是要记住,拦截器工作作为一个堆栈,并确保你添加logging器在所有的最后。
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());
我find了打印login改造的方法
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);
为我工作。
这里的大部分答案几乎涵盖了除了这个工具之外的所有东西,这是查看日志最酷的方法之一。
这是Facebook的Stetho 。 这是在谷歌浏览器上监控/logging您的应用程序的networkingstream量的绝佳工具。 你也可以在Github上find。
对于Retrofit 2.0.2的代码是这样的
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder httpClient=new OkHttpClient.Builder(); httpClient.addInterceptor(logging);
嘿家伙,我已经find解决办法:
public static <T> T createApi(Context context, Class<T> 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); }