i want to get other http code data same 400 , 401 and other with retrofit rx
its my code
#GET("sample")
Observable<String> getSample();
&
public Observable<String> getSample() {
return Domain.getApiClient(Tags.WRITHE_URL).getSample()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io());
}
&
new AppStore().getSample().subscribe(new DisposableObserver<String>() {
#Override
public void onNext(String value) {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
when http code 200 i can use data in on next
and other http code call on error
in onError i dont have access data of server
what should i do for get data when http code is other than 200?
non-200 response information is included in the exception passed to onError:
public void onError(Throwable e){
HttpException error = (HttpException)e; //you can use the instanceof check
int errorCode = error.response().code();
String errorBody = error.response().errorBody().string();
}
Related
I am wondering how can I get NMEA data type. It would be best if I could achieve this with Retrofit. The IP address of this data is http://213.73.2.250:5018. It looks like this: data
I have tried this with retrofit with this code:
public void getRestDataListRetrofit(final ViewMvpTextViewLocation viewMvpTextViewLocation) throws IOException {
Call<String> result = Api.getClient().getString();
result.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
viewMvpTextViewLocation.dismissProgressDialogWithSuccess(response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
viewMvpTextViewLocation.dismissProgressDialogWithError(call.request().toString() + " " + t.toString());
}
});
}
where Api class is
public class Api {
public static ApiInterface getClient() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://213.73.2.250:5018/")
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(ApiInterface.class);
}
}
and getString() method is
public interface ApiInterface {
#GET("/")
Call<String> getString();
}
When I click the button to receive this data I get with error: "unexpected status line: $GPGGA, (...) ". What is wrong with this code? Thanks in advance.
I did a workaround by parsing an error message that contains a text I wanted to have.
I am using retrofit library with post request, but i did not found data. Give "Internal server error" message.
API_1 : http://www.fabgrad.com/dummy_api_1/
type : POST
data : { us_id:23 }
interface -
public interface FirstApi {
public static String URl = "http://www.fabgrad.com/";
#FormUrlEncoded
#POST("dummy_api_1")
Call<Titles> getData(#Field("us_id") String id);
}
Using retrofi in main activity -
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(FirstApi.URl)
.addConverterFactory(GsonConverterFactory.create())
.build();
FirstApi categoryMenuApi = retrofit.create(FirstApi.class);
String s="23";
Call<Titles> categoryMenuCall = categoryMenuApi.getData(s);
categoryMenuCall.enqueue(new Callback<Titles>() {
#Override
public void onResponse(Call<Titles> call, Response<Titles> response) {
Titles list = response.body();
}
#Override
public void onFailure(Call<Titles> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
I am new in retrofit So please help
You only have to add / at the end of your endpoint #POST("dummy_api_1")
Just like:
#POST("dummy_api_1/")
I have a problem with Retrofit & Android.
I have API method "api/account/login". This method has Content-Type application/json and what about the body:
"Request body has to contain LoginData object serialized to JSON format and properly encrypted" (from api doc)
So, sample body:
"cUdu2LkEChP...Lw7R9m4="
Also, I have second API Method: "api/account/data", which have the same body and content-type.
What is my problem?
I am using Retrofit to connect with API.
interface APIService {
#POST("api/account/login")
void postLogin(#Body String encryptedCredentials, Callback<String> callback);
#POST("/api/account/data")
void postLoginData(#Body String encryptedCredentials, Callback<String> response);
}
for first method everything works fine, API returns what should return, but, for the second method Retrofit returns error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $
Actually now I have no idea what is going on, both methods take the same body, but only one is failing...
handling api-calls:
#Override
// THIS WORKS FINE!
public APIRequest postLoginRequest(final String encryptedCredentials) {
return new APIRequest() {
#Override
protected void fireRequest() {
APIServiece.postLogin(encryptedCredentials, new Callback<String>() {
#Override
public void success(String s, Response response) {
logicEventBus.post(new LoginEvent(null, s));
}
#Override
public void failure(RetrofitError error) {
logicEventBus.post(new LoginEvent(error, null));
}
});
}
};
}
#Override
// THIS DOESNT WORK FINE :(
public APIRequest postLoginDataRequest(final String encryptedCredentials, final AccountData.LoggedBy loggedBy) {
return new APIRequest() {
#Override
protected void fireRequest() {
Callback<String> callback = new Callback<String>() {
#Override
public void success(String s, Response response) {
logicEventBus.post(new LoginDataEvent(null, s));
}
#Override
public void failure(RetrofitError error) {
logicEventBus.post(new LoginDataEvent(error, null));
}
};
switch (loggedBy) {
case INTERNAL:
APIService.postLoginData(encryptedCredentials, callback);
break;
case FACEBOOK:
APIService.postLoginData(encryptedCredentials, callback);
break;
case GOOGLEPLUS:
APIService.postLoginData(encryptedCredentials, callback);
break;
}
}
};
}
I have checked in the debugger, strings are fine.
API also works fine (checked in Postman).
Debugger never get into "success" (in not-working method).
Thanks for any kind of help!
I am having trouble working out how to handle a response error with retrofit and RxAndroid. onError() gets called if there is a network error or the like but I need to be able to get the response to check if there was an authentication error. Instead what I get is a token with a null String and I can't find out why. What is the best way to go about this?
This is my RxAndroid call at the moment.
Client.getInstance().getService()
.getToken(usernameET.getText().toString(), passwordET.getText().toString())
.subscribe(new Subscriber<SiteInfo>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onNext(SiteInfo siteInfo) {
Log.d(TAG, "onNext "+ token.toString());
}
});
This is my retrofit service
#GET("my_url_here")
Observable<Token> getToken(
#Query("username") String username,
#Query("password") String password
);
This is my Current restadapter
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(BASE_URL)
.build();
service = restAdapter.create(MyService.class);
And this is my Token Class.
public class Token {
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
#Override
public String toString() {
return token;
}
}
How should I go about handlng this. Can it be done in the RxAndroid part or do I need to add something to my RestClient or maybe something else entirely?
Thanks.
Edit
07-01 06:38:04.562 1680-1793/uk.co.dyolo.thing D/Retrofit﹕ ---> HTTP GET my_website_here
07-01 06:38:04.562 1680-1793/uk.co.dyolo.thing D/Retrofit﹕ ---> END HTTP (no body)
07-01 06:38:04.610 1680-1793/uk.co.dyolo.thing D/Retrofit﹕ <--- HTTP 200 my_website_here (48ms)
07-01 06:38:04.610 1680-1793/uk.co.dyolo.thing D/Retrofit﹕ : HTTP/1.1 200 OK
I have found a solution
Firstly I expanded my Token object to have an error property.
public class Token {
private String token;
private String error;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
#Override
public String toString() {
return token;
}
}
Then I added an operator to my RxJava chain which can check to see if the error field is not null. And if there is an error, throw a custom exception which calls the subscribers onError allowing me to handle it.
if (token.getError() != null) {
throw OnErrorThrowable.from(new UserAuthenticationException(token.getError()));
}
And if there is an error, throw a custom exception which calls the subscribers onError allowing me to handle it.
if (e instanceof OnErrorThrowable){
if (e.getCause() instanceof UserAuthenticationException){
Log.d(TAG, "onError "+e.getCause().getMessage());
}
e.getCause().printStackTrace();
}
This is a bit late but if anyone wanders here, Retrofit 2 passes in instance of HttpException into the onError callback whenever the request returned from the server with an error code outside the [200,300) interval ...
throwable -> {
if(throwable instanceof HttpException){
switch(((HttpException)throwable).code()){
// your error handling logic
}
}
}
You can also retrieve the whole reponse from this object..
I am trying to send image files from my android app to a back end server. On Postman, images are sent and response code:200 is received.
However, trying to send images from my android app using retrofit, I keep receiving response code:500 Internal Server Error. Here is my code:
public interface RetrofitInterface {
#Multipart
#POST("uploads/addImage")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part image);
}
The NetworkClient
public class NetworkClient {
private static Retrofit retrofit;
public static Retrofit getRetrofit(){
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS).build();
if(retrofit == null){
String BASE_URL = "https://addimage.herokuapp.com/";
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).
addConverterFactory(GsonConverterFactory.create()).client(okHttpClient).build();
}
return retrofit;
}
}
And then the call
private void uploadImage(Uri imageUri){
File file = new File(imageUri.toString());
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", "image.jpg", requestBody);
Retrofit retrofit = NetworkClient.getRetrofit();
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
Call<ResponseBody> call = retrofitInterface.uploadImage(body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccessful()){
Log.d("UploadImage", "Yeepee!!! = "+response.message());
}else Log.d("UploadImage", "Response failure = "+response.message());
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof SocketTimeoutException) {
// "Connection Timeout";
Log.e("UploadImage", "Connection Timeout");
} else if (t instanceof IOException) {
// "Timeout";
Log.e("UploadImage", "Timeout");
} else {
//Call was cancelled by user
if(call.isCanceled()) {
Log.e("UploadImage", "Call was cancelled forcefully");
} else {
//Generic error handling
Log.e("UploadImage", "Network Error :: " + t.getLocalizedMessage());
}
}
}
});
}
I am not sure if it's a server error since images upload successfully from Postman. I am very confused and I am not sure what I am doing wrong.
According to your Postmen screen shot there is no key for image file can you try like below
remove this line
MultipartBody.Part body = MultipartBody.Part.createFormData("file", "image.jpg", requestBody);
And add this one
MultipartBody.Part body = MultipartBody.Part.createFormData("", "image.jpg", requestBody);
Generally 500 Internal Server error means there is something wrong in the server, but if the Postman is giving 200 that means the server part is OK, there's something wrong in your code.
try changing this line
File file = new File(imageUri.toString());
to this
File file = new File(imageUri.path);
And also make sure that the key name you used is same as the response key name
Thank you all for your responses. I have been able to resolve and it turned out to be a conflict between my request body and what the server was expecting.
For my case, I was sending a different mime-type(a .jpg), where the server developer made the server look for .jpeg and .png.
This was how I got to see the error and resolve the conflict.
Call<ResponseBody> call = retrofitInterface.uploadImage(body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccessful()){
Log.d("UploadImage", "Yeepee!!! = "+response.message());
}else {
Log.d("UploadImage", "Response failure = "+response.message());
try {
Log.d("UploadImage", "Response failure = "+response.errorBody().string());
} catch (IOException e) {
Log.d("UploadImage", "IOException = "+e.getMessage());
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof SocketTimeoutException) {
// "Connection Timeout";
Log.e("UploadImage", "Connection Timeout");
} else if (t instanceof IOException) {
// "Timeout";
Log.e("UploadImage", "Timeout");
} else {
//Call was cancelled by user
if(call.isCanceled()) {
Log.e("UploadImage", "Call was cancelled forcefully");
} else {
//Generic error handling
Log.e("UploadImage", "Network Error :: " + t.getLocalizedMessage());
}
}
}
});
The response.errorBody().string() got the error message from the server and I was able to resolve the conflict.