How to handle Call<Object> Response as String? - java

Im in a confusing spot right now. My API returns a Token for Login when posting a new User with UserData. How do I get the response.body() as a String to save it?
It only returns a Post object what I don't actually want. I only use it to create the Post.
private void createPost(User user) {
Post post = new Post(user.getName(), user.getGender(), user.getBirthyear(), user.getHeight(),user.getWeight());
Call<Post> call = jsonmongo.createPost(post);
// To execute it asynchron
call.enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (!response.isSuccessful()) {
Log.e("RESPONSECODE", ""+ response.code());
return;
}
Log.e("RESPONSECODE", ""+ response.code());
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
Log.e("RESPONSECODE", ""+ t.getMessage());
}
});
}
Get Response.Body and save it to the Database via SQL Adapter ( adapter.addToken(response.body()) )
response.body().toString only returns Object reference ( com.example.Resources.Post#4c8352 )
String S = new Gson().toJson(response.body())
Log.e("JSON", S)
Returns this:
E/JSON: {"age":0,"gender":0,"height":0,"weight":0}
Wanted output:
E/JSON: {"token":aslfjkhr9RRRRf283FGr3489pjfGGG34HH89fj}

let me try... you can use Gson library to create a String json object from the response.
Try it:
new Gson().toJson(response);

Related

How to return Retrofit Response inside a method in android?

I am learning Retrofit in android.
I am calling a Retrofit API inside a String method which returns a String. Generally calling the method it is returning the default value not the API response value.
I needed to wait till getting API response then assign to String variable and then return that value. How to do that? Anyone can help me please? Thanks in advance.
public String checkIsSubscribe(String video_user_id) {
final String[] is_subscribed = {"false"};
APIService apiService = RetrofitInstance.getRetrofitInstance().create(APIService.class);
Call<String> call = apiService.checkIfSubscribed(video_user_id, "2");
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.code() == 200 ){
String result = response.body();
Log.e("checkIfSub result = ", result);
if (result == "true"){
is_subscribed[0] = "true";
Log.e("checkIfSub innner = ", is_subscribed[0]);
}
}else{
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
return is_subscribed[0];
}

How to implement custom error handling with retroift2

I calling to the api with the basic retrofit Call object:
public interface dataApi {
#GET("animal/cats")
Call<AllAnimals> getAllData(
#Query("api_key") String apiKey
);
}
And I can get the response inside my view model like this:
call.enqueue(new Callback<AllAnimals>() {
#Override
public void onResponse(Call<AllAnimals> call, Response<AllAnimals> response) {
animals.setValue(response.body());
}
#Override
public void onFailure(Call<AllAnimals> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
Nothing speical here.
I've several problem with this approach
FIRST - if I give the wrong api key for example, the response should give me a response with the code of the problem, instead I just get null body.
SECOND I am planning to have more api calls, and it's a huge code duplication to handle errors every call I wrote.
How can I implement custom error handling for this situation, that will be apply to other calls too?
I think you can use okhttp interceptor and define yourself ResponseBody converter to fix your problem.
First,intercept you interested request and response;
Second,check the response,if response is failed then modify the response body to empty。
define a simple interceptor
Interceptor interceptor = new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
System.out.println(request.url());
okhttp3.Response response = chain.proceed(request);
if (!response.isSuccessful() && url.contains("animal/cats")) {
// request failed begin to modify response body
response = response.newBuilder()
.body(ResponseBody.create(MediaType.parse("application/json"), new byte[] {}))
.build();
}
return response;
}
};
define self ResponseBody converter
most code from com.squareup.retrofit2:converter-jackson we just add two lines:
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final ObjectReader adapter;
JacksonResponseBodyConverter(ObjectReader adapter) {
this.adapter = adapter;
}
#Override public T convert(ResponseBody value) throws IOException {
try {
if (value.contentLength() == 0) {
return null;
}
return adapter.readValue(value.charStream());
} finally {
value.close();
}
}
}
the below code is added:
if (value.contentLength() == 0) {
return null;
}

Java android retofit get

I did this and it doesn't work
#Headers("Accept: application/json")
#GET("objects/last_state/?modify_after={date}")
Call<State> getUpdate(#Header("Authorization") String token, #Path("date") String date);
on SyncHttpClient i did this :
syncHttpClient.get(context, "https://****/objects/last_state?modify_after=" + lastModify, headers, null, handler);
and it work. What did I do wrong in that?
I call this method :
MyApplication.retrofitInterface.getUpdate("SCToken " + singleton.getUid(), singleton.getLastModify()).enqueue(new Callback<State>() {
#Override
public void onResponse(Call<State> call, Response<State> response) {
Log.e("tak", "tak");
}
#Override
public void onFailure(Call<State> call, Throwable t) {
Log.e("nie", "nie");
}
});
Try use a #Query in Retrofit to this type of request with get (?=)
#Headers("Accept: application/json")
#GET("objects/last_state/")
Call<MovieResult> getAllMovies(#Header("Authorization") String token, #Query("modify_after") String date);
In Retrofit you need to express the ?modify_after={date} part of the path as a #Query("name") parameter of the method.
So, replace #Path("date") with #Query("modify_after"), and just put #GET("objects/last_state")

How can I post message in Retrofit2?

This project run with a web server. When user click button, it should post the message inside of EditText. I use Retrofit2 for it. The program has stoped when I click button.
ApiInterface.java
#POST("api/EmergencyNotification/SendNotification")
Call<SendMessageModel>postMessage(#Header("Authorization") String token,
// #Field(("PhotoRequest")) String photoRequest,
// #Field(("Location")) String location,
#Field(("MessageBody")) String messageBody);
// #Field(("AnswerValue")) String answerValue);
In the button OnClick this function runs:
protected void postMessage(){
startProgress();
String authorization = SessionHelper.getCustomerTokenWithBearer();
// Loc = lattitude + longitude;
Call<SendMessageModel> call = ApiService.apiInterface.postMessage(authorization,
mesaj.getText().toString().trim());
call.enqueue(new Callback<SendMessageModel>() {
#Override
public void onResponse(Call<SendMessageModel> call, Response<SendMessageModel> response) {
stopProgress();
if (response.isSuccessful()){
if (response.body() != null){
DialogHelper.showDialogWithOneButton("",response.body().getData());
}
}
else {
ApiErrorUtils.parseError(response);
}
}
#Override
public void onFailure(Call<SendMessageModel> call, Throwable t) {
stopProgress();
DialogHelper.showFailedDialog();
}
});
}
Ok. I solved it now. My api url was wrong and I added new #Multipart and #Part instead of #Field.
#POST("api/EmergencyNotification/SendMessage")
Call<SendMessageModel>postMessage(#Header("Authorization") String token,
#Part(("MessageBody")) String messageBody);
You are missing #FormUrlEncoded attribute since you are using field attribute instead of body
#POST("api/EmergencyNotification/SendNotification")
#FormUrlEncoded
Call<SendMessageModel>postMessage(#Header("Authorization") String token,
...

Handling Retrofit status codes without a pojo class

I got the following response from my server: status code 201 Created.
There is no actual response (returned object, etc.), so there is not need to create a POJO class.
So, I don't know how I should handle this status code without creating a POJO class. Is there any option to make write the code without using a POJO class?
Retrofit API has Response class that can encapsulate your response.
As long as you don't want to bother with the response data you can implement your service as:
interface CustomService {
#GET("whatever")
Call<Response<Void>> getAll();
// Or using RxJava:
#GET("whatever")
Single<Response<Void>> getRxAll();
}
Then implement your callback:
private Callback<Response<Void>> responseHandler = new Callback<Response<Void>>() {
#Override
public void onResponse(Call<Response<Void>> call, Response<Response<Void>> response) {
final int code = response.code();
// TODO: Do whatever you want with the response code.
}
#Override
public void onFailure(Call<Response<Void>> call, Throwable t) {
// TODO: Handle failure.
}
}
Or reactive consumer:
private Consumer<Response<Void>> responseRxHandler = new Consumer<Response<Void>>() {
#Override
public void accept(Response<Void> response) throws Exception {
final int responseCode = response.code();
// TODO: Do whatever you want with the response code.
}
};
Debugging result:
You can try the following code.
Can get the response without a POJO class by getting using ResponseBody format and then you can parse it normally like ordinary JSON parsing.
Api Call:
Call<ResponseBody> call = service.callLogin(AppConstants.mApiKey, model_obj);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.code() == 201)
{
JSONObject jobjresponse = null;
try {
jobjresponse = new JSONObject(mResponse.body().string());
String status = jobjresponse.getString("status");
JSONObject result = jobjresponse.getJSONObject("results");
String msg = result.getString(“msg”);
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
Retrofit Interface class:
public interface RetrofitInterface {
#Headers({"Content-Type: application/json", "Cache-Control: max-age=640000"})
#POST("v1/auth/")
public Call<ResponseBody> callLogin(#Query("key") String key, #Body LoginModel body);
public static final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(“base url”)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
Sample Response:
{ "status":"true", "result":{"msg”:”created successfully”} }

Categories