RxJava2 with Retrofit2-unable to get logs using HttpLoggingInterceptor - android

I have integrated RxJava2 with Retrofit2 and I am unable to get logs for api calls using HttpLoggingInterceptor.
I am using below dependencies-
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'io.reactivex.rxjava2:rxjava:2.0.2'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.9.1'
and using below code
public class RxJavaRetofit {
private ApiMethods api;
public RxJavaRetofit() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(AppUrls.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
api = retrofit.create(ApiMethods.class);
}
public void getSocialFeed(Context context, SocialRequest socialRequest, final mevorun.mevolife.com.mevorun.listeners.onSocialServiceResponseHandler onServiceResponseHandler) {
Utils.showDialog(context);
api.getSocialData(socialRequest).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Social>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Social value) {
try {
onServiceResponseHandler.onServerResponse(value.getResponse(),"Feed");
Utils.hideDialog();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
Utils.hideDialog();
}
});
}
In my Logcat I have selected Debug and searching HttpLoggingInterceptor but there is no log for that keyword.I tried in Verbose also but its not showing logs for api call.How can i get logs for my api call?

This almost a comment not really an answer.
Everything looks ok with your code. The interceptor logs with the tag OkHttp. Searching for that should yield the logs you are looking for.

Related

Unable to create call adapter for rx.Observable<model> for method xx

I have very new to rxJava and I'd like to chain 2 api call in sequence together using Retrofit. But keep getting this error: Unable to create call adapter for rx.Observable for method xx. Below are part of my codes:
ServiceA
.subscribeOn(rx.schedulers.Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<ResponseA, Observable<ResponseB>>() {
#Override
public rx.Observable<ResponseB> call(ResponseA fooA) {
// code to save data from service A to db
// call service B
return ServiceB;
}
})
.subscribe(new Subscriber<ResponseB>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(ResponseB fooB) {
// code to save data from service B to db
}
});
Retrofit retrofit = new Retrofit.Builder().baseUrl("xxx")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.3'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
you need to do something like this
val loginRequest = retrofitService.login(params)
loginRequest
.flatMap { response ->
saveLoginInfo(response.data)
return#flatMap retrofitService.getProfile(params) }
.flatMap { response ->
doSomethingWithProfile(response.data)
return#flatMap retrofitService.getItems(params) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe (
{ response ->
doSomethingWithItems(response.data)
doSomethingInMainThread()
},
{ err -> Log.v("TAG", err.localizedMessage) },
{ Log.v("TAG", "Chains Completed") }
)
Check more in the link

Cannot resolve method SubscribeOn - RxJava

I am very new to RxJava, I am trying to make Retrofit calls using RxJava. When I write this code on SubscribeOn it says 'Cannot resolve method SubscribeOn(io.reactivex.scheduler)'.
Could you guide on where I am doing it wrong.
Thanks
R
getDemoData in the Presenter layer.
void getDemoData(){
mCompositeDisposable.add(apiInterface.getDemoData()
//subscribeOn has the error.
.subscribeOn(Schedulers.io()) // "work" on io thread
.observeOn(AndroidSchedulers.mainThread()) // "listen" on UIThread
.map(new Function<IApiCalls, List<DemoJSONAPIData>>() {
#Override
public List<DemoJSONAPIData> apply(
#io.reactivex.annotations.NonNull final IApiCalls apiCalls)
throws Exception {
// we want to have the geonames and not the wrapper object
return apiCalls.getDemoData();
}
})
.subscribe(new Consumer<List<Geoname>>() {
#Override
public void accept(
#io.reactivex.annotations.NonNull final List<Geoname> geonames)
throws Exception {
//display
}
})
);
}
ApiInterface
public interface ApiInterface {
#GET("/posts")
//Single<DemoJSONAPIData> getDemoData();
Call<List<DemoJSONAPIData>> getDemoData();
}
IApiCalls
public interface IApiCalls {
List<DemoJSONAPIData> getDemoData();
}
ApiClient
public class ApiClient {
public static final String BASE_URL_TWO = "https://jsonplaceholder.typicode.com";
public static Retrofit retrofit = null;
public static Retrofit getApiClient()
{
if(retrofit == null)
{
retrofit = new Retrofit.Builder().baseUrl(BASE_URL_TWO)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
}
dependencies
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-jackson:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
Edit
My Retrofit call which I want to implement using RxJava/rxAndroid
#Override
public List<DemoJSONAPIData> getDemoData() {
try{
demoJSONAPIDatas = new ArrayList<>();
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<List<DemoJSONAPIData>> call = apiInterface.getDemoData();
call.enqueue(new Callback<List<DemoJSONAPIData>>() {
#Override
public void onResponse(Call<List<DemoJSONAPIData>> call, Response<List<DemoJSONAPIData>> response) {
Log.d("MainActivity", "Status Code = " + response.code());
demoJSONAPIDatas = response.body();
Log.d("demoJSONAPIDatas", demoJSONAPIDatas.toString());
for(DemoJSONAPIData demoJSONAPIData: demoJSONAPIDatas){
Log.d("UserId", demoJSONAPIData.getId());
Log.d("Title", demoJSONAPIData.getTitle());
}
}
#Override
public void onFailure(Call<List<DemoJSONAPIData>> call, Throwable t) {
Log.d("error", "error");
}
});
}catch (Exception e){
System.out.println("Error " + e.getMessage());
}
return demoJSONAPIDatas;
}
Error when using Single.
Check your import for observable in ApiInterface. it should be import io.reactivex.Observable;
This happened to me too. So when I go check my APIinterface, it has automatically imported the 'import android.database.Observable;' instead of 'import io.reactivex.Observable;'. When u change it to that all the errors were gone.
You probably added the wrong package.
These mistakes :
" import java.util.* " ---
" import android.database.Observable "
Actually:
" import io.reactivex.Observable "
You can make the necessary changes in the interface.
Just Import the following on the api interface
import rx.Observable;
and your problem will be solved
api.test(test)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Observer<BaseResponse>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(BaseResponse response) {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
Observable<BaseResponse> test(#Field("test") String isOnline);
import Observable from rx java.

How to get list of things in Retrofit

There's something about Retrofit that I'm not getting. I'm following examples on the web, but can't get it to even compile. I am able to access the data from the RESTful service via old school (i.e. HttpGet/HttpResoponse) so I know the service works. It returns a bunch of EmployeeData (as oppose to just one EmployeeData)
In the app gradle file:
dependencies {
...
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'
...
}
The url for the RESTful service endpoint is:
https://com.somewhere/PhoneDirectoryService/api/Employees/
I have defined a string for the base url:
<string name="https_phone_directory_service_baseurl">https://com.somewherePhoneDirectoryService/api/</string>
Interface
public interface EmployeesService {
#GET("Employees.json") // the string in the GET is end part of the endpoint url
public Call<List<EmployeeEndpointResponse>> listEmployees();
}
Response
public class EmployeeEndpointResponse {
private List<EmployeeData> employees; // EmployeeData is a POJO
// public constructor is necessary for collections
public EmployeeEndpointResponse() {
employees = new ArrayList<EmployeeData>();
}
public static EmployeeEndpointResponse parseJSON(String response) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
Type collectionType = new TypeToken<List<EmployeeData>>(){}.getType();
Gson gson = gsonBuilder.create();
EmployeeEndpointResponse employeeEndpointResponse = gson.fromJson(response, EmployeeEndpointResponse.class);
return employeeEndpointResponse;
}
}
Get the data
public static boolean getEmployeeData(Context context) {
Resources resources = context.getResources();
URI uri = null;
try {
uri = new URI(resources.getString(R.string.https_phone_directory_service_baseurl));
}
catch (URISyntaxException exception) {
Log.e("getEmployeeData", exception.toString());
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(uri.toString())
.addConverterFactory(GsonConverterFactory.create())
.build();
Call<List<EmployeeEndpointResponse>> call = service.listEmployees();
EmployeesService service = retrofit.create(EmployeesService.class);
// this does not compile
// error: <anonymous com.somewhere.utilities.Utilities$1> is not
// abstract and does not override abstract method
// onFailure(Call<List<EmployeeEndpointResponse>>,Throwable) in Callback
call.enqueue(new Callback<List<EmployeeEndpointResponse>>() {
#Override
public void onResponse(Response<List<EmployeeEndpointResponse>> response) {
List<EmployeeEndpointResponse> myList = response.body();
// Successfull request, do something with the retrieved messages
}
#Override
public void onFailure(Throwable t) {
// Failed request.
}
});
// so I tried this which gives compile error
// retrofit2.Callback<java.util.List
// <com.somewhere.gson.EmployeeEndpointResponse>>)
// in Call cannot be applied to anonymous retrofit2.Callback
// <com.somewhere.gson.EmployeeEndpointResponse>)
call.enqueue(new Callback<EmployeeEndpointResponse>() {
#Override
public void onResponse(Call<EmployeeEndpointResponse> call, Response<EmployeeEndpointResponse> response) {
// handle response here
EmployeeEndpointResponse employeeEndpointResponse = (EmployeeEndpointResponse)response.body();
}
#Override
public void onFailure(Call<EmployeeEndpointResponse> call, Throwable t) {
}
});
}
What do I need to do?
Data looks like:
[
{"Name":"Smith, Ken J.",
"Cell":"",
"EmailAddress":"Ken.Smith#somewhere.com",
"Location":"West",
"Phone":"555-555-5555",
"Address":"PO Box 555 5555 Del Norte",
"City":"Jackson",
"State":"WY",
"Zip":"85555",
"Latitude":42.24976,
"Longitude":-107.82171},
{"Name":"Cox, Daniel B.",
"Cell":"",
"EmailAddress":"daniel.cox#somewhere.com",
"Location":"West",
"Phone":"(555) 555-5516",
etc ...}
]
Add the dependency
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
}
Generate the http client
private static OkHttpClient getOkHttpClient(){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
return okClient;
}
Getting the data
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(YOUR_URL)
.client(getOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
EmployeesService service = retrofit.create(EmployeesService.class);
Call<EmployeeEndpointResponse> call = service.listEmployees();
call.enqueue(new Callback<EmployeeEndpointResponse>() {
#Override
public void onResponse(Call<EmployeeEndpointResponse> call, Response<EmployeeEndpointResponse> response) {
EmployeeEndpointResponse employeeEndpointResponse = response.body();
//manage your response
}
#Override
public void onFailure(Call<EmployeeEndpointResponse> call, Throwable t) {
}
});
Parsing JSON
Your POJO doesn't need any aditional methods to parse JSON. Just generate the code with GSON anotations with http://www.jsonschema2pojo.org/

RxJava + Retrofit -> BaseObservable for API calls for centralized response handling

I am new to RxJava so please forgive me if this sounds too newbie :-).
As of now I have an abstract CallbackClass that implements the Retofit Callback. There I catch the Callback's "onResponse" and "onError" methods and handle various error types before finally forwarding to the custom implemented methods.
I also use this centralized class to for request/response app logging and other stuff.
For example: for specific error codes from my sever I receive a new Auth token in the response body, refresh the token and then clone.enqueue the call.
There are of course several other global behaviors to the responses from my server.
Current solution (Without Rx):
public abstract void onResponse(Call<T> call, Response<T> response, boolean isSuccess);
public abstract void onFailure(Call<T> call, Response<T> response, Throwable t, boolean isTimeout);
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (_isCanceled) return;
if (response != null && !response.isSuccessful()) {
if (response.code() == "SomeCode" && retryCount < RETRY_LIMIT) {
TokenResponseModel newToken = null;
try {
newToken = new Gson().fromJson(new String(response.errorBody().bytes(), "UTF-8"), TokenResponseModel.class);
} catch (Exception e) {
e.printStackTrace();
}
SomeClass.token = newToken.token;
retryCount++;
call.clone().enqueue(this);
return;
}
}
} else {
onResponse(call, response, true);
removeFinishedRequest();
return;
}
onFailure(call, response, null, false);
removeFinishedRequest();
}
#Override
public void onFailure(Call<T> call, Throwable t) {
if (_isCanceled) return;
if (t instanceof UnknownHostException)
if (eventBus != null)
eventBus.post(new NoConnectionErrorEvent());
onFailure(call, null, t, false);
removeFinishedRequest();
}
My question is: Is there any way to have this sort of centralized response handling behavior before finally chaining (or retrying) back to the subscriber methods?
I found these 2 links which both have a nice starting point but not a concrete solution. Any help will be really appreciated.
Forcing request retry after custom API exceptions in RxJava
Retrofit 2 and RxJava error handling operators
Two links you provided are a really good starting point, which I used to construct solution to react to accidental
network errors happen sometimes due to temporary lack of network connection, or switch to low throughtput network standard, like EDGE, which causes SocketTimeoutException
server errors -> happen sometimes due to server overload
I have overriden CallAdapter.Factory to handle errors and react appropriately to them.
Import RetryWithDelayIf from the solution you found
Override CallAdapter.Factory to handle errors:
public class RxCallAdapterFactoryWithErrorHandling extends CallAdapter.Factory {
private final RxJavaCallAdapterFactory original;
public RxCallAdapterFactoryWithErrorHandling() {
original = RxJavaCallAdapterFactory.create();
}
#Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
}
public class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
private final Retrofit retrofit;
private final CallAdapter<?> wrapped;
public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<?> wrapped) {
this.retrofit = retrofit;
this.wrapped = wrapped;
}
#Override
public Type responseType() {
return wrapped.responseType();
}
#SuppressWarnings("unchecked")
#Override
public <R> Observable<?> adapt(final Call<R> call) {
return ((Observable) wrapped.adapt(call)).onErrorResumeNext(new Func1<Throwable, Observable>() {
#Override
public Observable call(Throwable throwable) {
Throwable returnThrowable = throwable;
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException) throwable;
returnThrowable = httpException;
int responseCode = httpException.response().code();
if (NetworkUtils.isClientError(responseCode)) {
returnThrowable = new HttpClientException(throwable);
}
if (NetworkUtils.isServerError(responseCode)) {
returnThrowable = new HttpServerException(throwable);
}
}
if (throwable instanceof UnknownHostException) {
returnThrowable = throwable;
}
return Observable.error(returnThrowable);
}
}).retryWhen(new RetryWithDelayIf(3, DateUtils.SECOND_IN_MILLIS, new Func1<Throwable, Boolean>() {
#Override
public Boolean call(Throwable throwable) {
return throwable instanceof HttpServerException
|| throwable instanceof SocketTimeoutException
|| throwable instanceof UnknownHostException;
}
}));
}
}
}
HttpServerException is just a custom exception.
Use it in Retrofit.Builder
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(new RxCallAdapterFactoryWithErrorHandling())
.build();
Extra: If you wish to parse errors that come from API (error that don't invoke UnknownHostException, HttpException or MalformedJsonException or etc.) you need to override Factory and use custom one during building Retrofit instance. Parse the response and check if it contains errors. If yes, then throw error and error will be handled inside the method above.
have you consider using the rxjava adapter for retrofit?
https://mvnrepository.com/artifact/com.squareup.retrofit2/adapter-rxjava/2.1.0
in your gradle file add
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
here's a interface for retrofit
public interface Service {
#GET("userauth/login?")
Observable<LoginResponse> getLogin(
#Query("v") String version,
#Query("username") String username,
#Query("password") String password);
}
and here's my implementation
Service.getLogin(
VERSION,
"username",
"password")
.subscribe(new Subscriber<LoginResponse>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(LoginResponse loginResponse) {
}
});
please note I'm using the gson converter factory to parse my response so I get an pojo (Plain Ole Java Object) returned.
See how you can do it.
Here is api call and pass Request model and response model in this.
public interface RestService {
//SEARCH_USER
#POST(SEARCH_USER_API_LINK)
Observable<SearchUserResponse> getSearchUser(#Body SearchUserRequest getSearchUserRequest);
}
This is the retrofit call,I used retrofit2
public RestService getRestService() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiConstants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(getOkHttpClient())
.build();
return retrofit.create(RestService.class);
}
//get OkHttp instance
#Singleton
#Provides
public OkHttpClient getOkHttpClient() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(httpLoggingInterceptor);
builder.readTimeout(60, TimeUnit.SECONDS);
builder.connectTimeout(60, TimeUnit.SECONDS);
return builder.build();
}
This is the api call, call it in your activity.
#Inject
Scheduler mMainThread;
#Inject
Scheduler mNewThread;
//getSearchUser api method
public void getSearchUser(String user_id, String username) {
SearchUserRequest searchUserRequest = new SearchUserRequest(user_id, username);
mObjectRestService.getSearchUser(searchUserRequest).
subscribeOn(mNewThread).
observeOn(mMainThread).
subscribe(searchUserResponse -> {
Timber.e("searchUserResponse :" + searchUserResponse.getResponse().getResult());
if (isViewAttached()) {
getMvpView().hideProgress();
if (searchUserResponse.getResponse().getResult() == ApiConstants.STATUS_SUCCESS) {
} else {
}
}
}, throwable -> {
if (isViewAttached()) {
}
});
}
Hope this will help you.

How to pretty print in Retrofit 2?

I have my retrofit set up with HttpLoggingInterceptor like this:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.setPrettyPrinting() // Pretty print
.create();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
On my Gson instance, I did setPrettyPrinting and I still get compact JSON outputs.
Here are my libraries.
compile 'com.google.code.gson:gson:2.5'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.0.1'
How can I acheive pretty printing using Retrofit 2?
Thanks.
EDIT: Updated my libraries and still didn't work
Inspired by Tanapruk's answer this is what I did to make it work with my versions of retrofit (2.1.0) and okhttp.logging-interceptor (3.8.1).
This version works for printing both JSON objects and arrays.
class ApiLogger : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
val logName = "ApiLogger"
if (message.startsWith("{") || message.startsWith("[")) {
try {
val prettyPrintJson = GsonBuilder().setPrettyPrinting()
.create().toJson(JsonParser().parse(message))
Log.d(logName, prettyPrintJson)
} catch (m: JsonSyntaxException) {
Log.d(logName, message)
}
} else {
Log.d(logName, message)
return
}
}
}
And in the client:
val httpClientBuilder = OkHttpClient.Builder()
val httpLoggingInterceptor = HttpLoggingInterceptor(ApiLogger())
httpLoggingInterceptor.level = Level.BODY
httpClientBuilder.addInterceptor(httpLoggingInterceptor)
create your own custom HttpLogginInterceptor.
public class CustomHttpLogging implements HttpLoggingInterceptor.Logger {
#Override
public void log(String message) {
final String logName = "OkHttp";
if (!message.startsWith("{")) {
Log.d(logName, message);
return;
}
try {
String prettyPrintJson = new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(message));
Log.d(logName, prettyPrintJson);
} catch (JsonSyntaxException m) {
Log.d(logName, message);
}
}
}
In your client, add:
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new CustomHttpLogging())
.build();
Thanks for Tanapruk Tangphianphan's answer.
I improve it for support all Java Platform not only for Android.
Create PrettyLogger class
class PrettyLogger implements HttpLoggingInterceptor.Logger {
private Gson mGson = new GsonBuilder().setPrettyPrinting().create();
private JsonParser mJsonParser = new JsonParser();
#Override
public void log(String message) {
String trimMessage = message.trim();
if ((trimMessage.startsWith("{") && trimMessage.endsWith("}"))
|| (trimMessage.startsWith("[") && trimMessage.endsWith("]"))) {
try {
String prettyJson = mGson.toJson(mJsonParser.parse(message));
Platform.get().log(INFO, prettyJson, null);
} catch (Exception e) {
Platform.get().log(WARN, message, e);
}
} else {
Platform.get().log(INFO, message, null);
}
}
}
Use in Buidler:
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new PrettyLogger());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(loggingInterceptor);
Beta 2 did not always respect custom gson settings. Try upgrading to Beta 3.
From the beta 3 change log --
Fix: The Gson converter now respects settings on the supplied Gson
instance (such as serializeNulls). This requires Gson 2.4 or newer.
You will also need to upgrade to okhttp3 for beta3.
Kotlin version that doesnot use gson:
HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
private fun print(m: String) {
//Crashlytics.log(m)
Log.i("API", m)
}
override fun log(message: String) {
if (message.length > 500)
return print("=== more than 500 characters ===")
if (message.startsWith("{") || message.startsWith("[")) try {
JSONObject(message).toString(4).also(::print)
} catch (e: JSONException) { print(message) }
else print(message)
}
}).also { it.level = HttpLoggingInterceptor.Level.BODY }

Categories

Resources