使用 Retrofit 2 记录日志
Logging with Retrofit 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@3ff4074d
headers:
Content-Type: application/vnd.ll.event.list+json
鉴于删除了我们过去与 Retrofit 1 一起使用的 setLog()
和 setLogLevel()
,我应该如何进行正确的日志记录?
大家好,我已经找到解决办法了:
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);
}
我不知道 setLogLevel() 是否会 return 在 Retrofit 的最终 2.0 版本中,但现在您可以使用拦截器进行日志记录。
可以在 OkHttp wiki 中找到一个很好的例子: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();
试试这个:
Request request = chain.request();
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
在此之后,body
中有您感兴趣的JSON。
这是一个记录请求和响应主体的 Interceptor
(使用 Timber,基于来自 OkHttp 文档的示例和其他一些 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";
}
}
}
需要在Retrofit中进行高级别日志记录的,使用这样的拦截器
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";
}
}`
在 Retrofit 2 中你应该使用 HttpLoggingInterceptor.
添加对 build.gradle
的依赖。截至 2019 年 10 月的最新版本是:
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'
创建一个 Retrofit
对象,如下所示:
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);
如果出现弃用警告,只需将 setLevel
更改为:
interceptor.level(HttpLoggingInterceptor.Level.BODY);
以上解决方案为您提供了 logcat 与
设置的旧消息非常相似的消息
setLogLevel(RestAdapter.LogLevel.FULL)
如果java.lang.ClassNotFoundException
:
较旧的 Retrofit 版本可能需要较旧的 logging-interceptor
版本。查看评论部分以了解详细信息。
我遇到了你,我试着问这本书的作者 Retrofit:喜欢在 Android[= 上使用 API 52=](这里是link)
(不!我不是为他们做广告……但他们真的是好人 :)
而且作者很快回复了我,在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();
这是如何在 HttpLoggingInterceptor 的帮助下添加日志记录方法。另外,如果你是我上面提到的那本书的 reader,你可能会发现它说 Retrofit 2.0 不再有日志方法——我问过作者,这是不正确的,他们会更新明年预定再说吧。
// 如果你对 Retrofit 中的 Log 方法不是很熟悉,我想再分享一些东西。
还应注意,您可以选择一些日志记录级别。我大部分时间都使用 Level.BODY,这会给出这样的结果:
你几乎可以在图中找到所有的http工作人员:header、content和response等
而且有时候你真的不需要所有的客人都来参加你的聚会:我只想知道它是否连接成功,在我的 Activiy & Fragmetn 中是否成功拨打了互联网电话。然后你可以自由使用 Level.BASIC,这将 return 像这样:
你能找到里面的状态码200 OK吗?就是这样:)
还有一个,Level.HEADERS,只会return网络的header。雅当然还有另一张照片:
这就是所有的日志技巧 ;)
并且我想与您分享我学到很多的教程there。他们有一堆很棒的 post 谈论几乎所有与 Retrofit 相关的东西,他们正在继续更新 post,同时 Retrofit 2.0 即将到来。请看一下这些工作,我认为这会为您节省很多时间。
我面临的主要问题是动态添加 headers 并将它们记录到调试 logcat 中。我试图添加两个拦截器。一个用于记录,一个用于添加 headers on-the-go(令牌授权)。问题是我们可能会使用 .addInterceptor 或 .addNetworkInterceptor。正如 Jake Wharton 对我说的:"Network interceptors always come after application interceptors. See https://github.com/square/okhttp/wiki/Interceptors"。所以这是 headers 和日志的工作示例:
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中的网络痕迹:
http://facebook.github.io/stetho/
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
builder.networkInterceptors().add(new StethoInterceptor());
}
然后在Chrome中打开"chrome://inspect"...
我在 Retrofit 中找到了打印日志的方法
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);
适合我。
如果您使用的是 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();
在 Retrofit 2 中正确执行此操作的最佳方法是将记录器拦截器添加为网络拦截器,这将打印出网络 headers 和您的自定义 headers。重要的是要记住拦截器作为堆栈工作,并确保在所有末尾添加记录器。
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());
这里的大部分答案几乎涵盖了除此工具之外的所有内容,这是查看日志的最酷方式之一。
Facebook's Stetho. This is the superb tool to monitor/log your app's network traffic on google chrome. You can also find here Github。
对于 Retrofit 2.0.2,代码如下
**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();
}
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)
这将创建一个带有日志记录的改造对象。无需创建单独的对象。
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();
首先添加对build.gradle的依赖:
实施'com.squareup.okhttp3:logging-interceptor:3.12.1'
在使用 Kotlin 时,您可以像这样添加日志记录拦截器:
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
}
}
这是使用 HttpLoggingInterceptor
从日志中过滤任何 request/response 参数的简单方法:
// 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);
这是完整的要点:
https://gist.github.com/mankum93/179c2d5378f27e95742c3f2434de7168
下面的一组代码对我来说没有任何问题
Gradle
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'
RetrofitClient
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
还可以通过进入 Android Studio 底部的 Profiler 选项卡来验证结果,然后单击 + 符号开始新会话,然后 select [=27] 中所需的尖峰=].在那里你可以获得一切,但它既麻烦又缓慢。请看下图。
改造日志
Retrofit 的拦截器是一个很棒的功能,它允许您处理 http 请求。
它们有两种类型:application
和 network
拦截器。
如果您需要记录 requests/responses,我建议您使用 Charles Web Debugging Proxy Application
。输出与 Stetho
非常相似,但它是更强大的工具,您不需要将其添加为应用程序的依赖项
我也被困在类似的情况下,setLevel()
方法没有出现,当我试图用 HttpLoggingInterceptor 的实例调用它时,
像这样:
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
我是这样解决的,为 Retrofit2 生成日志,
我想你已经添加了依赖项,
implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
你可以查看最新版本,这个link:
https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor)
这里他们也解释了如何添加。
我创建了一个名为 AddLoggingInterceptor
的 class,
这是我的代码,
public class AddLoggingInterceptor {
public static OkHttpClient setLogging(){
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build();
return okHttpClient;
}
}
然后,我们正在实例化我们的 Retrofit,
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(AddLoggingInterceptor.setLogging()) // here the method is called inside client() method, with the name of class, since it is a static method.
.build();
}
return retrofit;
}
现在您可以看到在您的 Android Studio 中生成的日志,您可能需要搜索,okHttp
以进行过滤过程。它对我有用。如果有任何问题,您可以在这里给我发短信。
如果java.lang.ClassNotFoundException
用匕首
我删除了
implementation("com.squareup.okhttp3:okhttp:4.9.0")
一切正常。
我正在尝试获取请求中发送的确切 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@3ff4074d
headers:
Content-Type: application/vnd.ll.event.list+json
鉴于删除了我们过去与 Retrofit 1 一起使用的 setLog()
和 setLogLevel()
,我应该如何进行正确的日志记录?
大家好,我已经找到解决办法了:
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);
}
我不知道 setLogLevel() 是否会 return 在 Retrofit 的最终 2.0 版本中,但现在您可以使用拦截器进行日志记录。
可以在 OkHttp wiki 中找到一个很好的例子: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();
试试这个:
Request request = chain.request();
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
在此之后,body
中有您感兴趣的JSON。
这是一个记录请求和响应主体的 Interceptor
(使用 Timber,基于来自 OkHttp 文档的示例和其他一些 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";
}
}
}
需要在Retrofit中进行高级别日志记录的,使用这样的拦截器
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";
}
}`
在 Retrofit 2 中你应该使用 HttpLoggingInterceptor.
添加对 build.gradle
的依赖。截至 2019 年 10 月的最新版本是:
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'
创建一个 Retrofit
对象,如下所示:
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);
如果出现弃用警告,只需将 setLevel
更改为:
interceptor.level(HttpLoggingInterceptor.Level.BODY);
以上解决方案为您提供了 logcat 与
设置的旧消息非常相似的消息setLogLevel(RestAdapter.LogLevel.FULL)
如果java.lang.ClassNotFoundException
:
较旧的 Retrofit 版本可能需要较旧的 logging-interceptor
版本。查看评论部分以了解详细信息。
我遇到了你,我试着问这本书的作者 Retrofit:喜欢在 Android[= 上使用 API 52=](这里是link) (不!我不是为他们做广告……但他们真的是好人 :) 而且作者很快回复了我,在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();
这是如何在 HttpLoggingInterceptor 的帮助下添加日志记录方法。另外,如果你是我上面提到的那本书的 reader,你可能会发现它说 Retrofit 2.0 不再有日志方法——我问过作者,这是不正确的,他们会更新明年预定再说吧。
// 如果你对 Retrofit 中的 Log 方法不是很熟悉,我想再分享一些东西。
还应注意,您可以选择一些日志记录级别。我大部分时间都使用 Level.BODY,这会给出这样的结果:
你几乎可以在图中找到所有的http工作人员:header、content和response等
而且有时候你真的不需要所有的客人都来参加你的聚会:我只想知道它是否连接成功,在我的 Activiy & Fragmetn 中是否成功拨打了互联网电话。然后你可以自由使用 Level.BASIC,这将 return 像这样:
你能找到里面的状态码200 OK吗?就是这样:)
还有一个,Level.HEADERS,只会return网络的header。雅当然还有另一张照片:
这就是所有的日志技巧 ;)
并且我想与您分享我学到很多的教程there。他们有一堆很棒的 post 谈论几乎所有与 Retrofit 相关的东西,他们正在继续更新 post,同时 Retrofit 2.0 即将到来。请看一下这些工作,我认为这会为您节省很多时间。
我面临的主要问题是动态添加 headers 并将它们记录到调试 logcat 中。我试图添加两个拦截器。一个用于记录,一个用于添加 headers on-the-go(令牌授权)。问题是我们可能会使用 .addInterceptor 或 .addNetworkInterceptor。正如 Jake Wharton 对我说的:"Network interceptors always come after application interceptors. See https://github.com/square/okhttp/wiki/Interceptors"。所以这是 headers 和日志的工作示例:
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中的网络痕迹: http://facebook.github.io/stetho/
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
builder.networkInterceptors().add(new StethoInterceptor());
}
然后在Chrome中打开"chrome://inspect"...
我在 Retrofit 中找到了打印日志的方法
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);
适合我。
如果您使用的是 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();
在 Retrofit 2 中正确执行此操作的最佳方法是将记录器拦截器添加为网络拦截器,这将打印出网络 headers 和您的自定义 headers。重要的是要记住拦截器作为堆栈工作,并确保在所有末尾添加记录器。
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());
这里的大部分答案几乎涵盖了除此工具之外的所有内容,这是查看日志的最酷方式之一。
Facebook's Stetho. This is the superb tool to monitor/log your app's network traffic on google chrome. You can also find here Github。
对于 Retrofit 2.0.2,代码如下
**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();
}
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)
这将创建一个带有日志记录的改造对象。无需创建单独的对象。
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();
首先添加对build.gradle的依赖:
实施'com.squareup.okhttp3:logging-interceptor:3.12.1'
在使用 Kotlin 时,您可以像这样添加日志记录拦截器:
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
}
}
这是使用 HttpLoggingInterceptor
从日志中过滤任何 request/response 参数的简单方法:
// 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);
这是完整的要点:
https://gist.github.com/mankum93/179c2d5378f27e95742c3f2434de7168
下面的一组代码对我来说没有任何问题
Gradle
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'
RetrofitClient
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
还可以通过进入 Android Studio 底部的 Profiler 选项卡来验证结果,然后单击 + 符号开始新会话,然后 select [=27] 中所需的尖峰=].在那里你可以获得一切,但它既麻烦又缓慢。请看下图。
改造日志
Retrofit 的拦截器是一个很棒的功能,它允许您处理 http 请求。
它们有两种类型:application
和 network
拦截器。
如果您需要记录 requests/responses,我建议您使用 Charles Web Debugging Proxy Application
。输出与 Stetho
非常相似,但它是更强大的工具,您不需要将其添加为应用程序的依赖项
我也被困在类似的情况下,setLevel()
方法没有出现,当我试图用 HttpLoggingInterceptor 的实例调用它时,
像这样:
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
我是这样解决的,为 Retrofit2 生成日志,
我想你已经添加了依赖项,
implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
你可以查看最新版本,这个link:
https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor)
这里他们也解释了如何添加。
我创建了一个名为 AddLoggingInterceptor
的 class,
这是我的代码,
public class AddLoggingInterceptor {
public static OkHttpClient setLogging(){
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build();
return okHttpClient;
}
}
然后,我们正在实例化我们的 Retrofit,
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(AddLoggingInterceptor.setLogging()) // here the method is called inside client() method, with the name of class, since it is a static method.
.build();
}
return retrofit;
}
现在您可以看到在您的 Android Studio 中生成的日志,您可能需要搜索,okHttp
以进行过滤过程。它对我有用。如果有任何问题,您可以在这里给我发短信。
如果java.lang.ClassNotFoundException
用匕首
我删除了
implementation("com.squareup.okhttp3:okhttp:4.9.0")
一切正常。