I tried to post raw data to server using retrofit method, but I receive the failure response like res fail: Response{protocol=http/1.1, code=500, message=Internal Server Error, url=http://192.168.1.9:8000/api/deviceinfo}
apiService = RetrofitSingleton.createService(ApiService.class);
spyApp = new SpyApp();
Call<ModelResponse> call = apiService.eventsUpdate(jsonObj);
call.enqueue(new Callback<ModelResponse>() {
#Override
public void onResponse(Call<ModelResponse> call, Response<ModelResponse> response) {
Log.e("response", new Gson().toJson(response.body())); //This shows null
if (response.isSuccessful()) {
String status = response.body().getData().getStatus();
} else {
Log.e("res fail", response.toString());
}
}
#Override
public void onFailure(Call<ModelResponse> call, Throwable t) {
Log.e("failure",t.getMessage());
}
});
Related
I am working with an Android Recyclerview with Retrofit, it is working without any Post Data. I need to post some data in my current Code.
Below is my Current ApiInterface
public interface ApiInterface {
#GET("mypage.php")
Call<Pojo> getData();
}
And in my activity I am calling this by below code
ApiInterface apiInterface = (ApiInterface) RetrofitClient.getRetrofitInstance().create(ApiInterface.class);
Call<Pojo> listingdata = apiInterface.getData();
listingdata.enqueue(new Callback<Pojo>() {
#Override
public void onResponse(Call<Pojo> call, Response<Pojo> response) {
if(response.isSuccessful()){
recycleradpter recycleradpter = new recycleradpter(response.body().getData());
recyclerView.setAdapter(recycleradpter);
progressbar2.setVisibility(View.GONE);
}
}
#Override
public void onFailure(Call<Pojo> call, Throwable t) {
//System.out.println("12345678934567890234567890");
//Toast.makeText(getActivity(), "No Connected internet", Toast.LENGTH_SHORT).show();
progressbar2.setVisibility(View.GONE);
dialogfunction();
}
});
How Can I get data based on passed data in above code
If you want to send a post request then you have to create a method like below. The calling of the method will be similar to that of get request. Just pass the parameters of your post body. You can for details here.
#POST("mypage.php")
Call<Pojo> postData(
#Field("param1") String param1,
#Field("param2") int param2
);
#FormUrlEncoded
#POST("your_php_file.php")
Call<ResponseBody> getLanguageCall(#Field("lang_code") String lang_code, #Field("app_id") String app_id);
private void getLanguageCall() {
progressDialog.setVisibility(VISIBLE);
Call<ResponseBody> call = ApiClient.getClient().create(ApiInterface.class).getLanguageCall(PreferenceManager.getStringPreference(SplashActivity.this, appLanguage), PreferenceManager.getStringPreference(SplashActivity.this, PreferenceManager.APP_ID));
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.setVisibility(View.GONE);
if (!response.isSuccessful()) {
showToast(response.code() + " : " + response.message());
return;
}
try {
JSONObject root = new JSONObject(response.body().string());
HashMap<String, String> list = new HashMap<String, String>();
JSONArray keyData = root.getJSONArray("key_data");
for (int i = 0; i < keyData.length(); i++) {
JSONObject obj = keyData.getJSONObject(i);
list.put(obj.getString("Key_Name").toLowerCase(), obj.getString("Key_Value"));
}
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
progressDialog.setVisibility(View.GONE);
showToast("Error ! Server Error.");
}
});
}
I am using retrofit 2.0 for download a file.the problem is enqueue method not called. there is no error and no catch. nothing happen, where is my mistake?
this is my interface:
public interface ApiService {
#GET("uploads/{file_name}")
Call<ServerResponse> downloadFile(#Path("file_name") String fileName);
}
and this is my downloading code :
private void downloadFile() {
progressDialog.show();
// Map is used to multipart the file using okhttp3.RequestBody
File file = new File(mediaPath);
// Parsing any Media type file
RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
ApiService getResponse = ApiClient.getClient().create(ApiService.class);
Call<ServerResponse> call = getResponse.downloadFile(file.getName());
call.enqueue(new Callback<ServerResponse>() {
#Override
public void onResponse(Call<ServerResponse> call, Response<ServerResponse> response) {
ServerResponse serverResponse = response.body();
if (serverResponse != null) {
if (serverResponse.getSuccess()) {
Toast.makeText(getApplicationContext(), serverResponse.getMessage(),Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), serverResponse.getMessage(),Toast.LENGTH_SHORT).show();
}
} else {
assert serverResponse != null;
Log.v("Response", serverResponse.toString());
}
progressDialog.dismiss();
}
#Override
public void onFailure(Call<ServerResponse> call, Throwable t) {
}
});
}
Probably, you are referring that the method "enqueue()" is called, but it's not the onResponse one.
Please wait some time (a minute is fine) and make sure that onResponse nor onFailure are called.
If you want more info, you can use the HTTP logging interceptor
#POST("uploads/{file_name}")
Observable<Document> getDocumentsList(#Path("file_name") String fileName);
and the code webservice call should be
Observable<Document> listObservable = mApiService.getDocumentsList(path);
subscribe(listObservable, new Consumer<Document>() {
#Override
public void accept(Document resourceDtos) throws Exception {
fillDocs(resourceDtos.getData());
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
fillDocs(throwable.getMessage());
}
});
I would like to handle my response from server , but I don't know how JSON (from server) its looks like. So I tried to display response as String , but I cant do it. Is it possible to display response as String? And then handle the response correctly. thanks
(Retrofit 1.9)
LoginService loginService = RetrofitClient.createService(LoginService.class);
loginService.searchOffer(getToken(), offerSearch, new Callback<String>() {
#Override
public void success(String offerSearchRequestResource, Response response) {
String responseFromSercer = response.getBody();
}
#Override
public void failure(RetrofitError error) {
}
});
change your response model to
JSONObject (from Gson)
then in your
public void success(...){response.body.toString();}
like this:
Call<JsonObject> call = YOUR_API_INTERFACE().YOUR_METHOD(YOUR_PARAMS);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, #NonNull Response<JsonObject> response) {
if(response.isSuccessful()) {
String responseFromSercer = response.body.toString();
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
.....
}
});
If you are sure the request runs successfully and there is a response back...use
System.out.println(response.getBody());
i'd also suggest you add Logging Interceptors here so that you can get a detailed view of all your API calls
I am using retrofit:2.1.0 and I am trying to save the response returned to my own POJO (UserProfile) but I can't seem to access the POJO, I assign the response to, outside of the callbacks.
So, in this call below, I want to have access to UserProfile outside of this call.
//adding `UserProfile userProfile;` outside of Call didn't help either
call.enqueue(new Callback<UserProfile>() {
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
}
}
#Override
public void onFailure(Call<UserProfile> call, Throwable t) {
//do something
}
});
//here userProfile is null and hence can't get status
Log.d(TAG, "Status outside of Call is: " + userProfile.getStatus());
New approach, same result
private List<UserProfile> userProfileList = new ArrayList<>();
call.enqueue(new Callback<UserProfile>() {
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
userProfileList.add(userProfile);
}
}
#Override
public void onFailure(Call<UserProfile> call, Throwable t) {
//do something
}
});
And this one gets fired even before callback and hence is null
if(userProfileList.size() > 0) {
for(UserProfile userProfile : userProfileList) {
Log.d(TAG, "Status is: " + userProfile.getStatus());
}
} else {
Log.d(TAG, "YakkerProfileList is NULL");
}
I added a setter in onResponse() which allowed me to use the response object elsewhere in the code like so:
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
//elsewhere in the code, I can read the value from this method
setUserProfile(userProfile.getStatus());
}
}
So when I make a POST API call to my server, I get a 400 Bad Request error with JSON response.
{
"userMessage": "Blah",
"internalMessage": "Bad Request blah blah",
"errorCode": 1
}
I call it by
Call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//AA
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//BB
}
}
However the problem is that once I get the response, onFailure() is invoke so that //BB is called. Here, I have no way to access the JSON response.
When I log the api request and response, it doesn't show JSON response at all. And Throwable t is IOException. However, strangely, when I make the same call on Postman, it does return the expected JSON response with 400 error code.
So my question is how can I get the json response when I get 400 Bad Request error? Should I add something to okhttpclient?
Thanks
You can do it in your onResponse method, remember 400 is a response status not an error:
if (response.code() == 400) {
Log.v("Error code 400",response.errorBody().string());
}
And you can handle any response code except 200-300 with Gson like that:
if (response.code() == 400) {
Gson gson = new GsonBuilder().create();
ErrorPojoClass mError=new ErrorPojoClass();
try {
mError= gson.fromJson(response.errorBody().string(),ErrorPojoClass.class);
Toast.makeText(context, mError.getDescription(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
// handle failure to read error
}
}
Add this to your build.gradle : compile 'com.google.code.gson:gson:2.7'
If you want create Pojo class go to Json Schema 2 Pojo and paste your example Json response. Select source type Json and annotation Gson .
You can try the below code to get 400 response. You can get error response from errorBody() method.
Call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//get success and error response here
if (response.code() == 400) {
if(!response.isSuccessful()) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(response.errorBody().string());
String userMessage = jsonObject.getString("userMessage");
String internalMessage = jsonObject.getString("internalMessage");
String errorCode = jsonObject.getString("errorCode");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//get failure response here
}
}
}
EDIT: Fixed method name from toString to string
Handle ErrorResponse with your class object
Kotlin
val errorResponse = Gson().fromJson(response.errorBody()!!.charStream(), ErrorResponse::class.java)
Java
ErrorResponse errorResponse = new Gson().fromJson(response.errorBody.charStream(),ErrorResponse.class)
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
DialogHelper.dismiss();
if (response.isSuccessful()) {
// Success
} else {
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(getContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
First step:
Create your POJO class for error response. In my case, ApiError.java
public class ApiError {
#SerializedName("errorMessage")
#Expose
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage= errorMessage;
}
}
Second Step:
Write below code in your api callback.
Call.enqueue(new Callback<RegistrationResponse>() {
#Override
public void onResponse(Call<RegistrationResponse> call, Response<RegistrationResponse> response)
{
if (response.isSuccessful()) {
// do your code here
} else if (response.code() == 400) {
Converter<ResponseBody, ApiError> converter =
ApiClient.retrofit.responseBodyConverter(ApiError.class, new Annotation[0]);
ApiError error;
try {
error = converter.convert(response.errorBody());
Log.e("error message", error.getErrorMessage());
Toast.makeText(context, error.getErrorMessage(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<RegistrationResponse> call, Throwable t) {
//do your failure handling code here
}
}
Here ApiClient.retrofit is your retrofit instance which is static.
I got similar issue, but existing code was stick to RxJava 2 chain.
Here's my solution:
public static <T> Observable<T> rxified(final Call<T> request, final Class<T> klazz) {
return Observable.create(new ObservableOnSubscribe<T>() {
AtomicBoolean justDisposed = new AtomicBoolean(false);
#Override
public void subscribe(final ObservableEmitter<T> emitter) throws Exception {
emitter.setDisposable(new Disposable() {
#Override
public void dispose() {
request.cancel();
justDisposed.set(true);
}
#Override
public boolean isDisposed() {
return justDisposed.get();
}
});
if (!emitter.isDisposed())
request.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, retrofit2.Response<T> response) {
if (!emitter.isDisposed()) {
if (response.isSuccessful()) {
emitter.onNext(response.body());
emitter.onComplete();
} else {
Gson gson = new Gson();
try {
T errorResponse = gson.fromJson(response.errorBody().string(), klazz);
emitter.onNext(errorResponse);
emitter.onComplete();
} catch (IOException e) {
emitter.onError(e);
}
}
}
}
#Override
public void onFailure(Call<T> call, Throwable t) {
if (!emitter.isDisposed()) emitter.onError(t);
}
});
}
});
}
transforming 400-like responses into rx chain is pretty simple:
Call<Cat> request = catApi.getCat();
rxified(request, Cat.class).subscribe( (cat) -> println(cat) );
Here is the simplest solution,
If you want to handle the response from onFailure method:
#Override
public void onFailure(Call<T> call, Throwable t) {
HttpException httpException = (HttpException) t;
String errorBody = httpException.response().errorBody().string();
// use Gson to parse json to your Error handling model class
ErrorResponse errorResponse = Gson().fromJson(errorBody, ErrorResponse.class);
}
Or if you are using rxjava Observable with Kotlin, handle it from error body:
{ error ->
val httpException :HttpException = error as HttpException
val errorBody: String = httpException.response().errorBody()!!.string()
// use Gson to parse json to your Error handling model class
val errorResponse: ErrorResponse =
Gson().fromJson(errorBody, ErrorResponse::class.java)
}
Don't forget to properly handle json to class conversion (use try-catch if not sure).
simply use
if (throwable is HttpException && (throwable!!.code() == 400 || throwable!!.code()==404)){
var responseBody = throwable!!.response()?.errorBody()?.string()
val jsonObject = JSONObject(responseBody!!.trim())
var message = jsonObject.getString("message")
tvValMsg.set(message)
}
This is how you can handle the response message
I am handling for error 500 you can add as much you want
switch (response.code()) {
case HttpURLConnection.HTTP_OK:
break;
case HttpURLConnection.HTTP_UNAUTHORIZED:
callback.onUnAuthentic();
break;
case HttpURLConnection.HTTP_INTERNAL_ERROR:
try {
String errorResponse = response.errorBody().string();
JSONObject object = new JSONObject(errorResponse);
String message = "Error";
if (object.has("Message"))
message = String.valueOf(object.get("Message"));
callback.onError(message);
} catch (IOException e) {
e.printStackTrace();
}
break;
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
case HttpURLConnection.HTTP_CLIENT_TIMEOUT:
default:
callback.onNetworkError();
break;
}
IF you are getting 400(Bad Request) by using retrofit first make sure are are setting input to API is Only Model class, If not then replace input request by Model class and then check you will get Success response.
#POST("api/users/CreateAccount")
Call<CreateAccount> createAccount(#Body CreateAccount model, #Header("Content-Type") String content_type);