It would be great if you share some knowledge with me! Here is my problem - we have an Android app. and a server. For some of the calls the client needs to send a previously obtained token from the server which is legit for a limited amount of time. If it happens that the token is not valid any more, an error is returned from the sever, a new token needs to be obtained and we need to retry the request.
But how can I handle such behavior with Retrofit? Any thoughts?
Thank you in advance!
How about you try and make a request with a callback, if the callback is a failure and the error message is that the token needs to be obtained, then you do a request to get the new token for example:
connectionInterface.getSomeStuff(object, new Callback<ObjectPOJO>() {
#Override
public void success(ObjectPOJO objectPOJO, Response response) {
//success
}
#Override
public void failure(RetrofitError error) {
if (error.getLocalizedMessage().equals("Token expire error")
connectionInterface.getToken();
}
Then in your retrofit getToken callback, if it is a success you will redo the getSomeStuff method and if it is a failure, you let the user know. For example:
connectionInterface.getToken(token, new Callback<token>() {
#Override
public void success(token token, Response response) {
//success and token has been added
//add the token to your request somehow...
connectionInterface.updateToken(token);
connectionInterface.getSomeStuff();
}
#Override
public void failure(RetrofitError error) {
//error let user know
}
Let me know if you have any other question. I think this will be the easiest way of doing it.
Related
How to check this condition and then send to server when refresh token?
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
Here is my code to send server. But is it send all time when app login ? How to send when above condition?
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("NEW_TOKEN", s);
sendRegistrationToServer(s);
}
private void sendRegistrationToServer(String token) {
APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
Call<Fcm> call = apiInterface.postFCMToken(user_id, newToken);
call.enqueue(new Callback<Fcm>() {
#Override
public void onResponse(Call<Fcm> call, Response<Fcm> response) {
}
#Override
public void onFailure(Call<Fcm> call, Throwable t) {
}
});
}
In general, you should expect that an app installation is unable to reliably detect when an FCM token changes. As such, any new token should be unconditionally reported to the backend, as a potential target for messaging for the given user.
The server side of your app can remove invalid tokens by looking at the error response when attempting to send a message to a token that's no longer valid. If you're using the Admin SDK to send a message to a device token, you can detect then when a token is invalid because the API will generate the error messaging/registration-token-not-registered, according to the documentation.
Following this tutorial I manage to get token. How now I use this to token to get tweets from user, for example?
Where should I place this token variable and make API call with retrofit?
twitterApi.postCredentials("client_credentials").enqueue(new Callback<OAuthToken>() {
#Override
public void onResponse(Call<OAuthToken> call, Response<OAuthToken> response) {
token = response.body(); // <---- my token
}
#Override
public void onFailure(Call<OAuthToken> call, Throwable t) {
// fail
}});
You could add it in all requests using interceptors, as descibed here How to use interceptor to add Headers in Retrofit 2.0
I am implementation for Retrofit on api call using images-upload base64Encode string. it is sending data perfect but Retrofit return response Internal Server Error 500 and i am sending request type is Body custom class. Plz help me what i do.
#Headers("Accept:application/json")
#POST(RestClient.postRegister)
Call<RegisterResp> getRegisterResponse(#Body RequestRegisterVo requestRegisterVo);
Call<RegisterResp> call = MyApplication.getRestClient().getApplicationServices().getRegisterResponse(requestRegisterVo);
call.enqueue(new Callback<RegisterResp>() {
#Override
public void onResponse(Call<RegisterResp> call, Response<RegisterResp> response) {
if (Other.isValidResp(response)) {
// success Log.i(TAG,"Register successfully");
} else {
hideDialog();
}
}
#Override
public void onFailure(Call<RegisterResp> call, Throwable t) {
hideDialog();
showToast(t.getMessage());
}
});
The same issue I had to face it, I got a solution in my case-
there is parameter issue, I was sending parameters in String and at the backend, they required Integer parameters.
You also checkout may be there is the issue with parameters or second reason is the URL issue so check it URL also.
I am making call using the following callback method:
Callback<PeopleList> callback = new Callback<PeopleList>() {
#Override
public void onResponse(Response<PeopleList> response) {
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Throwable t) {
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
}
};
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofit.create(MyService.class).getPeopleData().enqueue(callback);
To the following interface:
public interface MyService {
#Headers("Accept: application/json")
#GET("/data/people/")
Call<PeopleList> getPeopleData();
}
This callback works just fine on successful requests. On unsuccessful ones however it does not give me the opportunity to investigate further as the onFailure method does not allow me to retrieve the http error code that came with the response.
On investigating further I found that according to several stackoverflow threads, the onResponse method should be called even on unsuccessful requests. This however seems to be at odds not only with my personal experience but also with the documentation of the Callback interface, which states that:
Communicates responses from a server or offline requests. One and only one method will be
invoked in response to a given request.
So the question is, how do I get the HTTP error code from a failed response if the onResponse method isn't called?
I think that the onResponse method gets called even if there is a response with an Error so something like this might work(sorry if I did something wrong first attempt to answer anybody :)
#Override
public void onResponse(Response<PeopleList> response) {
if(response.isSuccess()){ //good http request, do something with response.body()....
Toast.makeText(LoginActivity.this,getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
} else { //bad http response do something with error message
try {
Toast.makeText(LoginActivity.this,response.errorBody().string().toString(), Toast.LENGTH_SHORT).show();
} catch (IOException e){
//IOException caught from response.errorBody().string() method
}
}
}
onResponse() will be always called, for failed requests .body() is null. response.isSuccess() is used to quickly distinguish requests with http codes between 200 and 300.
If you want to access http codes you can do the following:
int htppResultCode = response.raw().code();
It accesses the raw Response object which holds information about general outcome of the request.
I've seen answer to both of these questions, however, when I tried to put them together, I couldn't make it work. The problem itself is pretty simple: I want to get a string from one site and use it in a post request. That means I can only make the post request after I've finished parsing the GET request. The main ideas I'm using are these ones:
How to return response header field to main method using Google Volley for HTTP GET request in Android / Java?
Can I do a synchronous request with volley?
However the synchronous request is blocked and doesn't go on, and the first one is Async.
I believe this to be a simple thing to do, but still, I haven't be able to do it...
Thanks for any help!
Why not do something like this:
// send first request
requestQueue.add(firstRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
// send second request
requestQueue.add(secondRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));