handle 2 different error response for success and failer retrofit2 - java

My current success response is this:
{"status":"success","message":"msg here"}
with code 200
And my error response is this:
{"status":"failure","message":"There was a validation error","errors":{"shippingAddress":{"phoneNumber":"Please enter a valid phone number"}}}
with code 400
my problem is the code below is not working because it always go inside onFailure()
if (response.isSuccessful()) {
// do something
} else if (response.code() == 400) {
Gson gson = new Gson();
ErrorPhone message = null;
if (response.errorBody() != null) {
message = gson.fromJson(response.errorBody().charStream(), ErrorPhone.class);
}
if (message != null) {
Toast.makeText(context, message.getErrors().getShippingAddress().getPhoneNumber(), Toast.LENGTH_LONG).show();
} else {
String errors = "";
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
errors = jObjError.getJSONObject("errors").getJSONObject("shippingAddress").getString("phoneNumber");
} catch (JSONException | IOException e) {
e.printStackTrace();
}
if (!errors.equals("")) {
Toast.makeText(context, errors, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, response.message(), Toast.LENGTH_LONG).show();
}
}
}
and inside onFailure i cant listen to errorBody to handle the response

Use Retrofit interface called onResponse and place your code there. As Retrofit uses two different callback methods for the two possible outcomes of a network requests: either a failure or a successful request. Retrofit will call the appropriate callback method depending on the result. If the request was successful, Retrofit will also pass you the response of the server.
For more view this link:https://square.github.io/retrofit/2.x/retrofit/retrofit2/Callback.html and https://futurestud.io/tutorials/java-basics-for-retrofit-callbacks that will help you more to learn about retrofit Call-backs

Related

How to upload Multiple Images using Array List in android

I try many solutions but no once work for me.
I'm receiving images data in this way:
ArrayList<String> filePaths = data.getStringArrayListExtra(Pix.IMAGE_RESULTS);
and uploading images using multipart
MultipartBody requestBody = builder.build();
Call<Status_Response> call = taskMetServer.uploadMultiplePics(requestBody.parts());
call.enqueue(new Callback<Status_Response>() {
#Override
public void onResponse(Call<Status_Response> call, Response<Status_Response> response) {
if(response.isSuccessful()){
Status_Response status_response = response.body();
assert status_response != null;
String msg = status_response.getStatus();
Log.d("myMessage", "\n\nStatus: "+msg);
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), "Success " + response.message()+response.code(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Status_Response> call, Throwable t) {
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
my interface is:
#POST("test/store")
Call<Status_Response> uploadMultiplePics(
#Body List<MultipartBody.Part> images
);
but still receiving null in response instead of true of false:
2021-03-20 17:36:38.076 10582-10582/com.example.ourproductapp D/myMessage: [/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20210320-WA0082.jpeg]
2021-03-20 17:36:38.732 10582-10582/com.example.ourproductapp D/myMessage: Status: null
Thanks in advance
check your backend service, your server is getting file or not.
or you can use https://github.com/gotev/android-upload-service library

What causes the ErrorListener registered to a volley request to be triggered?

This page says that we can register a Listener to a volley request for handling errors:
https://developer.android.com/training/volley/simple
But it doesn't mention what kind of errors trigger this listener. Volley javadoc doesn't say anything about it either.
Specifically, will this listener be executed if a network error occurs.
I'm asking this because I've encountered an android code of the following form:
private void method() {
String URL = "";
final int[] status_code = new int[1];
StringRequest request = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (status_code[0] == 200) {
// do something
} else {
// display toast
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// display toast
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
status_code[0] = response.statusCode;
return super.parseNetworkResponse(response);
}
};
// add request to queue
}
This code seems to suggest that the registered ErrorListener isn't called for network errors.
What are the conditions which cause the ErrorListener registered to a Volley request to be called
The ErrorListener is triggered for 4xx responses and 5xx responses I cannot tell what happens though for the 3xx redirection responses as it didn't happended to me.
Here is a list with all HTTP Response codes:
https://www.restapitutorial.com/httpstatuscodes.html
I'm not exactly privy to your entire code but poking through the Volley source code:
Response.java takes in VolleyError object
VolleyError references NetworkResponses in its use.
Inspecting NetworkResponses deals with mainly HTTP status codes.
Also I'd note that VolleyError extends Exception.
So I would say the call back method is triggered when an Exception is thrown and VolleyError deals with HTTP status codes.
I just call this statement
#Override
public void onErrorResponse(VolleyError error) {
if (error instanceof TimeoutError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.error_network_timeout));
} else if (error instanceof ServerError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.error_server));
} else if (error instanceof NetworkError) {
//toast or log your error
} else if (error instanceof ParseError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.parse_error));
} else {
Log.i(TAG, "onErrorResponse: Something went wrong ");
}
You don't need to find error code

Android Volley : Supported status codes issue

I have used a restful API in my android application with the volley library, as I know in restful API we should implement STATUS CODES in special situation, but as I checked volley codes in this path : volley\toolbox\BasicNetwork.java I see volley only accepts status codes between 200 and 299.
if (statusCode < 200 || statusCode > 299) {
throw new IOException();
}
Why?
Does this mean volley does not support RESTFUL architectural?
VolleyError has a variable of type NetworkResponse that is public. You can access error.networkResponse.statusCode to implement your http error codes.
public void onErrorResponse(VolleyError error) {
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
// Deserialize data using what you want
JSONObject obj = new JSONObject(res);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (JSONException e2) {
e2.printStackTrace();
}
}
}
You can read more about this here. Android Volley - BasicNetwork.performRequest: Unexpected response code 400
If the server STATUS_CODE is in between 200 - 299 it is considerably a success status and Volley will fire the onResponse callback.
The code:
if (statusCode < 200 || statusCode > 299) {
throw new IOException();
}
Just simply means: When the status code IS NOT IN BETWEEN 200 - 299 therefore it is an error and Volley will fire the onErrorResponse callback instead.

Post photo on Facebook group using graph api

I'm working on an android app for a Facebook group. Using the graph API, I can easily post a text status but when I upload a photo, it returns error saying
(#100) The picture is not properly formatted
If I use the same code to post to my wall, the photo upload works fine.
Is this an API restriction or there is a separate approach to upload a photo to a group?
Following is my code:
Request photoRequest = Request.newUploadStagingResourceWithImageRequest(session, bitmap, new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (mProgress != null && mProgress.isShowing())
mProgress.dismiss();
if (response.getError() == null) {
Toast.makeText(NewPostActivity.this, "Successfully shared on the group", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(NewPostActivity.this, "Facebook sharing error: " + response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
}
}
});
Bundle params = photoRequest.getParameters();
if(message != null) {
params.putString("message", message);
}
if(imageBytes != null) {
params.putByteArray("picture", imageBytes);
}
photoRequest.setParameters(params);
photoRequest.setHttpMethod(HttpMethod.POST);
photoRequest.setGraphPath(Constants.URL_FEEDS);
photoRequest.executeAsync();
EDIT
I'm using Graph API v2.3
It does seem to be possible to post a photo in a group.
You can make a POST request to photos edge from the following paths:
/{group_id}/photos
When posting to this edge, a Photo will be created.
Link
Return type
Struct {
id: numeric string,
post_id: token with structure: Post ID,
}
It seems like the POST request to /<group-id>/feed doesn't allow to upload a photo (which otherwise works for /me/feed). I finally got this working with the /<group-id>/photos edge as suggested. Following is my code - hoping that it helps some:
Request photoRequest = Request.newUploadStagingResourceWithImageRequest(session, bitmap, new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (mProgress != null && mProgress.isShowing())
mProgress.dismiss();
if (response.getError() == null) {
Toast.makeText(NewPostActivity.this, "Successfully shared on the group", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(NewPostActivity.this, "Facebook sharing error: " + response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
}
}
});
Bundle params = photoRequest.getParameters();
if(message != null) {
params.putString("message", message);
photoRequest.setGraphPath(Constants.URL_FEEDS);
}
if(imageBytes != null) {
params.putByteArray("picture", imageBytes);
photoRequest.setGraphPath(Constants.URL_PHOTOS);
}
photoRequest.setParameters(params);
photoRequest.setHttpMethod(HttpMethod.POST);
photoRequest.executeAsync();

Retrofit2 - Upload image to server give an Internal Server Error as response in android studio

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.

Categories

Resources