Cannot deserialize nested JSON using Retrofit (Android) - android

I have JSON wrapped by "_embedded" tag like below:
{
"_embedded" : {
"events" : [ { ... }]}
I'm using retrofit with interface:
public interface IEventRest {
#GET("/events/search/findByPlaceId")
Observable<List<Event>> getEventList(#Query("placeId")String placeId);
}
And this is my REST class:
public class EventRest implements IEventRest {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Event[].class, new MyDeserializer())
.create();
private Retrofit getRetrofitClient() {
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
final OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(UrlUtils.URL)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
#Override
public Observable<List<Event>> getEventList(String placeId) {
final IEventRest placeRest = getRetrofitClient().create(IEventRest.class);
return placeRest.getEventList(placeId)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread());
}
private class MyDeserializer implements JsonDeserializer<List<Event>> {
#Override
public List<Event> deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
JsonElement content = je.getAsJsonObject().get("_embedded");
Type collectionType = new TypeToken<Collection<Event>>(){}.getType();
return new Gson().fromJson(content, collectionType);
}
}
}
But calling placeRest.getEventList(placeId) throws exception:
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:57)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: rx.exceptions.OnErrorNotImplementedException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:386)
at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:383)
at rx.internal.util.ActionSubscriber.onError(ActionSubscriber.java:44)
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:152)
at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.checkTerminated(OperatorObserveOn.java:276)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:219)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:351)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:9860)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:221)
Could you help me to find out what is wrong? Thank you in advance.

I have JSON wrapped by "_embedded" tag
And that is exactly the problem. Gson doesn't know that your data is wrapped, it only cares that at the string that it sees, it is an object.
Pulling the preview, from here... We get a total of three objects
Event.java
(This wasn't generated because you left out what the JSON looks like)
Embedded.java
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Embedded {
#SerializedName("events")
#Expose
private List<Event> events = new ArrayList<Event>();
public Embedded() {
}
public Embedded(List<Event> events) {
this.events = events;
}
public List<Event> getEvents() {
return events;
}
public void setEvents(List<Event> events) {
this.events = events;
}
}
Response.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Response {
#SerializedName("_embedded")
#Expose
private Embedded embedded;
public Response() {
}
public Response(Embedded embedded) {
this.embedded = embedded;
}
public Embedded getEmbedded() {
return embedded;
}
public void setEmbedded(Embedded embedded) {
this.embedded = embedded;
}
}
And, so now, Retrofit cares about a Call<Response>, which you can then call .getEmbedded().getEvents()
Or, you could mess around with MyDeserializer more, since that seems to be the issue with the existing code.

Related

Retrofit 2.3 Handling SocketTimeoutException

I'm currently using Retrofit 2.3 and RxAndroid for Android as my network communications. Its working fine most of the time. But sometimes, I get a SocketTimeOut exception (I'm assuming due to issues with the internet). I want to be able to handle this case but, putting a try catch around my retrofit calls in my activity doesn't catch this. Likewise, it doesn't go to the OnError method either (I don't see an option for an OnFailure method). The exception, instead, is shown in my RetrofitHelper class, at the return statement of the intercept method. Here is my Retrofit helper class:
public class RetrofitHelper {
/**
* The APICalls communicates with the json api of the API provider.
*/
public APICalls getAPICalls() {
final Retrofit retrofit = createRetrofit();
return retrofit.create(APICalls.class);
}
/**
* This custom client will append the "username=demo" query after every request.
*/
private OkHttpClient createOkHttpClient() {
final OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
final Request original = chain.request();
final HttpUrl originalHttpUrl = original.url();
final HttpUrl url = originalHttpUrl.newBuilder()
.build();
// Request customization: add request headers
final Request.Builder requestBuilder = original.newBuilder()
.url(url);
final Request request = requestBuilder.build();
return chain.proceed(request);
}
});
return httpClient.build();
}
/**
* Creates a pre configured Retrofit instance
*/
private Retrofit createRetrofit() {
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // Library for parsing json responses
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // Library for easier threading/background processing
.client(createOkHttpClient())
.build();
}
}
And here is my interface for my API calls
public interface APICalls {
#GET("Vehicle/VehiclePositions.json")
Single<ResponseVehiclePosition> getVehiclePositions();
#GET("TripUpdate/TripUpdates.json")
Single<ResponseTripUpdate> getTripUpdates();
}
And here is the log:
2020-06-05 15:43:34.877 10007-10007/com.samramakrishnan.campusbustracker E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.samramakrishnan.campusbustracker, PID: 10007
java.net.SocketTimeoutException: failed to connect to transitdata.cityofmadison.com/204.147.0.120 (port 80) from /10.0.2.16 (port 35902) after 10000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java:191)
at libcore.io.IoBridge.connect(IoBridge.java:135)
at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
at java.net.Socket.connect(Socket.java:621)
at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:63)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:223)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:149)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:192)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at com.samramakrishnan.campusbustracker.restapi.RetrofitHelper$1.intercept(RetrofitHelper.java:55)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
at okhttp3.RealCall.execute(RealCall.java:69)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
at io.reactivex.Single.subscribe(Single.java:2558)
at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
at io.reactivex.Scheduler$1.run(Scheduler.java:134)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
I think you are able to catch the exception by the BiConsumer in the subscribe method when you call do the GET call.
According to the source file:
public final Disposable subscribe(final Consumer<? super T> onSuccess, final Consumer<? super Throwable> onError)
so I think you can do something like:
compositeDisopsable.add(getAPICalls().getVehiclePositions()
.subscribeOn(...)
...
.subscribe( response -> {
//do what you want to do with the `response`
}, throwable -> {
if(throwable instanceOf SocketTimeoutException){
//handle your exception
});

Android Crashing With Retrofit static Instance

When I use the static Retrofit object the application crashing with the below log
I cannot use the retrofit object without static because i am using it too often. Please let me know the workaround for the same
W/WindowAnimator: Failed to dispatch window animation state change.
android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:513)
at android.view.IWindow$Stub$Proxy.onAnimationStopped(IWindow.java:548)
at com.android.server.wm.WindowAnimator.updateWindowsLocked(WindowAnimator.java:302)
at com.android.server.wm.WindowAnimator.animateLocked(WindowAnimator.java:694)
at com.android.server.wm.WindowAnimator.access$000(WindowAnimator.java:56)
at com.android.server.wm.WindowAnimator$1.doFrame(WindowAnimator.java:128)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
at android.view.Choreographer.doCallbacks(Choreographer.java:698)
at android.view.Choreographer.doFrame(Choreographer.java:630)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:882)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
Some Time i get this error too
Fail to sendHttpRequest
java.lang.IllegalArgumentException: HTTP entity may not be null
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:115)
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:151)
at miui.util.ErrorReport.c(SourceFile:396)
at miui.util.ErrorReport.sendReportRequest(SourceFile:353)
at miui.util.ErrorReport$1.a(SourceFile:369)
at miui.util.ErrorReport$1.doInBackground(SourceFile:366)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Here is the retrofit object which is working fine
public static Retrofit getAPIClient(Context context) {
return new Retrofit.Builder()
.baseUrl(context.getString(R.string.base_url))
.client(getOkHttpClient(context))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(getGson()))
.build();
}
But when I converted this to static it is crashing
if ( appApiClient == null ) {
appApiClient = new Retrofit.Builder()
.baseUrl( context.getString( R.string.base_url ) )
.client( getOkHttpClient( context)
.addCallAdapterFactory( RxJavaCallAdapterFactory.create() )
.addConverterFactory( GsonConverterFactory.create( getGson() ) )
.build();
}
return appApiClient ;
public class RetroFitServiceGenerator {
MySharedPreferences sharedPreferences;
public static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static Retrofit retrofit = builder.build();
public static HttpLoggingInterceptor logging = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
private static Context context;
private OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
public RetroFitServiceGenerator(Context context) {
this.context = context;
}
public <S> S serviceNOAuth(
Class<S> serviceClass) {
httpClient.addInterceptor(logging);
builder.client(httpClient.build());
retrofit = builder.build();
return retrofit.create(serviceClass);
}
}
Now you can modify or add Services based on your requirement like cache or authentication
and in your Class you just need to call :
RetrofitAPI service = new RetroFitServiceGenerator(context).serviceNOAuth(RetrofitAPI.class);

how to retrive json object using retrofit 2

I'am trying to retrieve this in my class but i got an error Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
my response from web service is {"last_question":"0","level":"0","error":"0"}
thank you
Json
{"last_question":"0","level":"0","error":"0"}
Activtiy
//calling from MainActivity
private void get()
{
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
API mApi = retrofit.create(API.class);
Call<Example> call = mApi.getdata();
call.enqueue(new Callback<Example>()
{
#Override
public void onResponse(Call<Example> call, Response<Example> response)
{
System.out.println(response.body().getError());
}
#Override
public void onFailure(Call<Example> call, Throwable t)
{
System.out.println(t.getMessage());
}
});
}
//pojo class
public class Example {
private String last_question;
private String level;
private String error;
//all getter andd setter are is here
}
Update:
Your server doesn't respond with your desired response. In fact its HTML-Code which is returned:
<html><body><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("9cc75ba79032859c712d6ecb862cfde7");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="http://advancedcalc.byethost8.com/test.php?i=2";</script><noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript></body></html>
Old (wrong) answer:
You forgot to add #SerializedName(name) Annotations to your fields within the Example class:
#SerializedName("last_question")
private String last_question;
#SerializedName("level")
private String level;
#SerializedName("error")
private String error;

Retrofit Error : No Retrofit annotation found. (parameter #1)

I'm a beginner in Android programming. just started.
Now I'm trying to communicate between Android and Tomcat server using retrofit.
but whenever I click login button, this error keeps me crazy.
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
Here are my errors..
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
for method NetworkService.postLogin
at com.example.ab.MainActivity.networkServiceModule(MainActivity.java:68)
at com.example.ab.MainActivity$1.onClick(MainActivity.java:50)
I added these in gradle
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
Interface :
public interface NetworkService {
#POST("/Attendance/login.jsp")
Call<PostJson> postLogin(PostJson postJson);
}
some part of MainActivity :
ApplicationController application = ApplicationController.getInstance();
application.buildNetworkService("xxx.xxx.xxx.xxx",8080);
networkService = ApplicationController.getInstance().getNetworkService();
login_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String ID = id.getText().toString();
String Pwd = password.getText().toString();
networkServiceModule(ID,Pwd); //this is line 50.
}
});
public void networkServiceModule(String ID, String Pwd){
Log.d("networkServiceModule","ID : "+ID);
Log.d("networkServiceModule","PW : "+Pwd);
Call<PostJson> thumbnailCall = networkService.postLogin(new PostJson(ID,Pwd)); //this is line 68.
thumbnailCall.enqueue(new Callback<PostJson>() {
#Override
public void onResponse(Response<PostJson> response, Retrofit retrofit) {
if(response.isSuccess()) {
String resultCode = response.body().getResult_code().toString();
Toast.makeText(getBaseContext(), "Login : " + resultCode, Toast.LENGTH_SHORT).show();
} else {
int statusCode = response.code();
Log.d("networkServiceModule", "response Code : "+statusCode);
}
}
ApplicationController :
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import retrofit.GsonConverterFactory;
import retrofit.Retrofit;
public class ApplicationController extends Application {
private static ApplicationController instance;
public static ApplicationController getInstance() {
return instance;
}
#Override
public void onCreate() {
super.onCreate();
ApplicationController.instance = this;
}
private NetworkService networkService;
public NetworkService getNetworkService() {
return networkService;
}
private String baseUrl;
public void buildNetworkService(String ip, int port) {
synchronized (ApplicationController.class) {
baseUrl = String.format("http://%s:%d", ip, port);
Gson gson = new GsonBuilder()
.create();
GsonConverterFactory factory = GsonConverterFactory.create(gson);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(factory)
.build();
networkService = retrofit.create(NetworkService.class);
}
}
}
I've kept trying to apply some solutions that I got from StackOverflow, but failed to find one for mine..
This is my first question on StackOverFlow, sorry for codes looking ugly.
You forgot to annotate the retrofit method parameter. Try the following
#POST("/Attendance/login.jsp")
Call<PostJson> postLogin(#Body PostJson postJson);
the problem is with PostJson postJson, every former parameter has to be associated with a retrofit annotation. In your case that should be the body of your post request.
Call<PostJson> postLogin(#Body PostJson postJson);
Though this answer is not specifically related to question, I found myself here while solving the issue. I solved it, therefore sharing.
I was trying to use retrofit along with coroutines and getting error Retrofit Error : No Retrofit annotation found. (parameter #2) , even though there was no parameter #2.
/**
* Suspend function to get media of the day for the day when this function is called.
* Will return a Media object in the response.
*/
#GET("planetary/apod")
suspend fun getTodaysMedia(#Query("api_key") apiKey: String): Media
Solved this by upgrading the retrofit version: version_retrofit = "2.9.0"
You forgot to annotate the retrofit method's parameters #Body like
#POST("/Attendance/login.jsp")
Call<PostJson> postLogin(#Body PostJson postJson);

retrofit httpLogInterceptor java.lang.NoSuchMethodError:

I was going through HttpLogInterceptor achieve to print log.but it was happened a error.
10-04 05:22:55.753 21294-21851/com.tc.retorfit_okhttp_cache_technique E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.tc.retorfit_okhttp_cache_technique, PID: 21294
java.lang.NoSuchMethodError: No virtual method log(Ljava/lang/String;)V in class Lokhttp3/internal/Platform; or its super classes (declaration of 'okhttp3.internal.Platform' appears in /data/data/com.tc.retorfit_okhttp_cache_technique/files/instant-run/dex/slice-okhttp-3.3.0_b69c4d16ac6ddca06e0d47d36f15c48706942fa9-classes.dex)
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.access$100(RealCall.java:33)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:120)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
The error is in the following code:
public interface Logger {
void log(String message);
/** A {#link Logger} defaults output appropriate for the current platform. */
Logger DEFAULT = new Logger() {
#Override public void log(String message) {
Platform.get().log(message);//Here have a error,NoSuchMethodError
}
};
}
My code is int following code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_print_log);
HttpLoggingInterceptor httpLoggingInterceptor=new HttpLoggingInterceptor();//compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient=new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl("https://api.github.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
final PrintLogActivity.GitHubApi repo=retrofit.create(PrintLogActivity.GitHubApi.class);
Call<List<Contributor>> responseBodyCall = repo.getContributors("square","retrofit");
responseBodyCall.enqueue(new Callback<List<Contributor>>() {
#Override
public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
Gson gson=new Gson();
if (response.body()!=null&&response.body().size()>0){
for (Contributor contributor:response.body()){
Log.i("contributor",contributor.getLogin());
}
}else{
Log.i("contributor","list is null");
}
}
#Override
public void onFailure(Call<List<Contributor>> call, Throwable t) {
Log.e("contributor","reuquire fail");
}
});
responseBodyCall.cancel();
}
interface GitHubApi{
#GET("repos/{owner}/{repo}/contributors")
Call<ResponseBody> contributorsBySimpleGetCall(#Path("owner") String own, #Path("repo") String repo);
#GET("users/{user}")
Call<ResponseBody> getUser(#Path("user") String user);
#GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> getContributors(#Path("owner") String own,#Path("repo") String repo);
}
make sure your okHttp and logging-interceptor have same version in build.gradle
like
com.squareup.okhttp3:okhttp:3.4.1
and
com.squareup.okhttp3:logging-interceptor:3.4.1
here versions are same 3.4.1.
make sure your okHttp and logging-interceptor have same version in build.gradle. And also don't forget to add compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
which will help you to get rid of exception
Static interface methods are only supported starting with Android N (--min-api 24): void okhttp3.logging.HttpLoggingInterceptor$Logger.lambda$static$0(java.lang.String)
My Logger interface implementation:
public interface Logger {
void log(String message);
/** A {#link Logger} defaults output appropriate for the current platform. */
Logger DEFAULT = new Logger() {
#Override public void log(String message) {
Platform.get().log(Platform.WARN,message,null);
}
};
}

Categories

Resources