HttpLoggingInterceptor for http request & response

2020-03-25 05:01发布

问题:

I'm using retrofit2 and I need to log all request and response. Request and response works perfectly, All I need is to log those request/response, I tried almost every solution, which I found here, but did not find solution. I don't understand what's wrong is here

this is my code

class Factory {

    private final static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    private static NetworkApi.Factory serverApi;
    private static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();

    private Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(RequestApi.BASE_URL)
            .client(httpClient.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    public static NetworkApi getApi() {
        if (BuildConfig.DEBUG){
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            httpClient.addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request.Builder builder = chain.request().newBuilder()
                            .addHeader("Content-Type", "application/json");
                    return chain.proceed(builder.build());
                }
            });

            httpClient.interceptors().add(interceptor);
        }
        if (serverApi == null){
            serverApi = new NetworkApi.Factory();
        }
        return serverApi.retrofit.create(NetworkApi.class);
    }
}

libraries :

compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'

回答1:

Try to use the OkHttpClient as follows:

private OkHttpClient createDefaultOkHttpClient() {
  HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
  interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
  return new OkHttpClient().newBuilder()
          .addInterceptor(interceptor)
          .build();
}

Then just set this to your retrofit builder:

Retrofit retrofitAsync = new Retrofit.Builder()
            .baseUrl(BASE_URL_APPS)
            .client(createDefaultOkHttpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(rxAdapter)
            .build();


回答2:

Make API call like this.

ApiFactory.java

public class ApiFactory {

/**
 * Base URL for API calls
 */
private static final String BASE_URL = "";

public ApiFactory() {
}

private static Retrofit provideRestAdapter() {

    return new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(BaseApplication.getInstance().getOkHttpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .addConverterFactory(ScalarsConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}

public static <S> S createService(Class<S> serviceClass) {
    return provideRestAdapter().create(serviceClass);
}

}

LoginService Interface

public interface LoginService {

/**
 * To Post FormUrlEncoded to web service
 *
 * @return Call Object of Type JsonObject
 */

@FormUrlEncoded
@POST("api/login")
Call<JsonObject> login(@Field("email") String email,
                       @Field("password") String password,
                       @Field("devicetype") String devicetype,
                       @Field("deviceid") String deviceid);

}

Make API call here

private void emailLoginRequest() {
    LoginService loginService = ApiFactory.createService(LoginService.class);
    Call<JsonObject> call = loginService.login(edtEmail.getText().toString(),edtPassword.getText().toString(),mDeviceType,mDeviceToken);
    call.enqueue(new Callback<JsonObject>() {
        @Override
        public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
            hideProgressDialog();
            if (response.isSuccessful()) {
                LOGD(TAG, "onResponse 0: " + response.body().toString());
                LoginResponse loginResponse = new Gson().fromJson(response.body().toString(), LoginResponse.class);

                System.out.println("+++ get message >> " + loginResponse.getMessage());
                int status = loginResponse.getStatus();

            }else {
                LOGD(TAG, "response fail 0: " + response.body());
            }
        }

        @Override
        public void onFailure(Call<JsonObject> call, Throwable t) {
            hideProgressDialog();
            LOGD(TAG, "onFailure: " + t.getMessage());
        }
    });
}

LoginResponse Make changes as per yours.

public class LoginResponse {

@SerializedName("status")
@Expose
private Integer status;
@SerializedName("message")
@Expose
private String message;
@SerializedName("data")
@Expose
private Data data;

/**
 * No args constructor for use in serialization
 *
 */
public LoginResponse() {

Sample response model
            //        {
    //            "status": 1,
    //                "data": {
    //            "user_id": "565464564",
    //                    "email": "email@email.com",
    //                    "fullname": "james",
    //                    "username": "james123",
    //                    "country": "54654654",
    //                    "city": "56546465546",
    //                    "token": "dfgdfgdfg545465465464564"
    //        },
    //            "message": "Login successfull"
    //        }
}

/**
 *
 * @param message
 * @param status
 * @param data
 */
public LoginResponse(Integer status, String message, Data data) {
    this.status = status;
    this.message = message;
    this.data = data;
}

/**
 *
 * @return
 * The status
 */
public Integer getStatus() {
    return status;
}

/**
 *
 * @param status
 * The status
 */
public void setStatus(Integer status) {
    this.status = status;
}

/**
 *
 * @return
 * The message
 */
public String getMessage() {
    return message;
}

/**
 *
 * @param message
 * The message
 */
public void setMessage(String message) {
    this.message = message;
}

/**
 * @return The data
 */
public Data getData() {
    return data;
}

/**
 * @param data The data
 */
public void setData(Data data) {
    this.data = data;
}

public class Data {

    @SerializedName("user_id")
    @Expose
    private String userId;

    @SerializedName("email")
    @Expose
    private String email;

    /**
     * No args constructor for use in serialization
     */
    public Data() {
    }

    /**
     * @param email
     * @param userId
     */
    public Data(String userId, String email) {
        this.userId = userId;
        this.email = email;
    }

    /**
     * @return The userId
     */
    public String getUserId() {
        return userId;
    }

    /**
     * @param userId The user_id
     */
    public void setUserId(String userId) {
        this.userId = userId;
    }

    /**
     * @return The email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @param email The email
     */
    public void setEmail(String email) {
        this.email = email;
    }

}
}

Enjoy!



回答3:

I it would be better to add interceptors while creating client using Builder as below code. If you notice we add two interceptors - Network interceptor > addNetworkInterceptor - Interceptor > addInterceptor

The main difference is network interceptor only works when there is a real request (not loading from caching). Interceptor log data on both cases loading from network or cache.

Also make sure you are imorting the correct BuildConfig (sometimes autocompletion import it from one of your libraries, then it will be always false)

`OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor.Logger networkLayerLogger = new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    LogUtils.d("NetworkLayer", message);
                }
            };

            HttpLoggingInterceptor.Logger appLayerLogger = new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                LogUtils.d("ApplicationLayer", message);
            }
        };
        HttpLoggingInterceptor networkLogging = new HttpLoggingInterceptor(networkLayerLogger);
        HttpLoggingInterceptor appLogging = new HttpLoggingInterceptor(appLayerLogger);

        networkLogging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
        appLogging.setLevel(HttpLoggingInterceptor.Level.BODY);

        clientBuilder.addNetworkInterceptor(networkLogging);
        clientBuilder.addInterceptor(appLogging);
    }

`