Receiving an empty body in retrofit Response - android

I am using retrofit to get data from http URL.
My Interface Class :
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
retrofit.Call<JSONObject> getSlots();
}
My request method.
public void getResponse(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
//Creating an object of our api interface
SlotsAPI api = retrofit.create(SlotsAPI.class);
retrofit.Call<JSONObject> callback = api.getSlots();
callback.enqueue(new Callback<JSONObject>() {
#Override
public void onResponse(Response<JSONObject> response) {
if (response != null) {
Log.d("OnResponse", response.body().toString());
}
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
}
In the response I am receiving an empty body.And the server responds with 200 OK.
D/OnResponse: {}
But when I open the URL in browser I am getting JSONObject on the screen.

you should try like this way ....
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
Call<JsonElement> getSlots();
}
in request method
retrofit.Call<JsonElement> callback = api.getSlots();
callback.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Response<JsonElement> response) {
if (response != null) {
Log.d("OnResponse", response.body().toString());
}
}

Please check your JsonObject. If you want to get response in json you must be define a response type JsonObject not JSONObject other wise specify the pojo class in your interface.

I think you are not understanding the retrofit filosofy.
The correct interface should be:
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
JSONObject getSlots();
}
When you call the getSlots method, retrofit will automatically do the HTTP request and return the JSONObject.
You will need to do this out of the main thread.

Make sure that the url of #Get is relative path
#Base URL: always ends with /
#Url: DO NOT start with /
Example:
String URL = http://api.co/base/ ;
And
#GET("webservice/syncdown")
JSONObject getSlots();
You may receiving a list of Slots. the Gson converter will handle it if you sending array of json
#GET(url)
retrofit.Call<List<Slot>> getSlots();

You are using the retrofit 2 or 1? The version 2 still is in beta.
If you are using the version 1. Use this:
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
void getSlots(Callback<JsonElement> callback);
}
With this the call will be asynchronous.

Same problem here, and answer from curiousMind saved my day.
More on the same subject: if you need to get a value from a pair use:
String value = response.body().getAsJsonObject().get("pair_name").getAsString();

Call<Void> getSlots() worked for me.

private void APIRetrofit_method() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RecyclerInterface.JSONURL)
// .client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
RecyclerInterface api = retrofit.create(RecyclerInterface.class);
Call<ResponseBody> call = api.getString(); /// GET METHOD without passing params
// Post METHOD CODE START
// HashMap<String, String> params = new HashMap<String, String>();
// params.put("name", "yuva");
// params.put("pass", "" + "123");
// Call<ResponseBody> call1 = api.getProspectList(params);
// Post METHOD CODE END

call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.d(TAG, "GetProspectlistresponse" + "" + response.isSuccessful());
utility.hideProgressDialog();
if (response.isSuccessful()) {
String remoteResponse = new String(response.body().string());
Log.d(TAG, "Holidaylistresponse" + "" + remoteResponse);
try {
JSONObject object = new JSONObject(remoteResponse);
JSONArray array = object.getJSONArray("Holidays_Details");
if (array.toString().equals("[]")) {
holiday_recyclerView.setVisibility(View.GONE);
} else {
holiday_recyclerView.setVisibility(View.VISIBLE);
for (int i = 0; i < array.length(); i++) {
JSONObject c = array.getJSONObject(i);
String holidayDate = c.getString(TAG_HOLIDAYDATE);
String holidayName = c.getString(TAG_HOLIDAYName);
String holidaytype = c.getString(TAG_HOLIDAYtype);
HashMap<String, String> customers = new HashMap<String, String>();
customers.put(TAG_HOLIDAYDATE, holidayDate);
customers.put(TAG_HOLIDAYName, holidayName);
customers.put(TAG_HOLIDAYtype, holidaytype);
arrayList.add(customers);
}
getHolidaylistAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
utility.hideProgressDialog();
}
} catch (IOException e) {
e.printStackTrace();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i("ErrorResponsestring", call.toString());
}
});
}
String JSONURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/";
#GET("json_parsing.php")
Call<ResponseBody> getString();
// #POST("getProspectList")
// #FormUrlEncoded
// Call<ResponseBody> getProspectList(#FieldMap HashMap<String, String> body);
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.squareup.okhttp3:okhttp:4.0.0'

Related

Retrofit2 returns 999 when I called api

I use Retrofit2 to call api, when I do apiTest("http://xxx.xx.xx.xxx:xxxx/", "T001", "Futek10911-01"), the response.code is 999 but it returns correct value in Postman. Where's the problem?
private void apiTest(String url, String machId, String check) throws JSONException {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
MyAPIService myAPIService = retrofit.create(MyAPIService.class);
JSONObject jsonObject = new JSONObject();
jsonObject.put("MACHID", machId);
jsonObject.put("CHECK", check);
Call<GetHostTime> call = myAPIService.getHostTime("sRequest", jsonObject);
call.enqueue(new Callback<GetHostTime>() {
#Override
public void onResponse(Call<GetHostTime> call, Response<GetHostTime> response) {
if(response.isSuccessful()){
Log.d("response ", "isSuccessful");
}else {
Log.d("response code ", response.code() + "");
}
}
#Override
public void onFailure(Call<GetHostTime> call, Throwable t) {
Log.d("Failure", t.getMessage());
}
});
public interface MyAPIService {
#POST("TcLeaseParkAPI/api/ParkingAPI/GetHostTime")
#FormUrlEncoded
Call<GetHostTime> getHostTime(#Field("MACHID") String key, #Field("CHECK") JSONObject jsonObject);
}
Comparing your Postman request and your code. It is clear I feel you are sending the request in wrong manner.
So we modify your Retrofit request as follows
public interface MyAPIService {
#POST("TcLeaseParkAPI/api/ParkingAPI/GetHostTime")
#FormUrlEncoded
Call<GetHostTime> getHostTime(#Field("sRequest") JSONObject jsonObject);
And then your request Call as follows
Call<GetHostTime> call = myAPIService.getHostTime(jsonObject);
Now your JSONObject will go in the key sRequest

Getting error code 400 bad request in retrofit but works on postman

I'm working on an Registraion API
which takes the json input as follow / request perameters
{"httpMethod":"POST",
"firstname":"Ali",
"lastname":"Patel",
"email":"alipatel05#gmail.com",
"password":"12345678",
"country":"Canada",
"state":"Quebec",
"city":"Montreal",
"type":"Parent"}
but when i call the api from android app it gives me bad response with error code 400 but works pretty fine on postman.
my API Client
public class APIClient {
private static Retrofit retrofit = null;
public static final String BASE_URL = "https://5r8ndtx9zc.execute-api.us-east-2.amazonaws.com/";
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
/*Gson gson = new GsonBuilder()
.setLenient()
.create();*/
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
my API interface
public interface APIInterface {
#Headers({
"Content-Type: application/json;charset=utf-8",
"Accept: application/json;charset=utf-8",
"Cache-Control: no-cache"
})
#POST("vaccinesApi")
Call<ResponseBody> registerUser(#Body JSONObject locationPost);
}
and here's my api call
private void registerUser() {
HashMap<String, String> newhashMap = new HashMap<>();
JSONObject hashMap = new JSONObject();
try {
hashMap.put("httpMethod","POST");
hashMap.put("firstname",mEditFirstName.getText().toString().trim());
hashMap.put("lastname",mEditLastName.getText().toString().trim());
hashMap.put("email",mEditEmail.getText().toString().trim());
hashMap.put("password",mEditPassword.getText().toString().trim());
hashMap.put("country","Canada");
hashMap.put("state","Quebec");
hashMap.put("city",mSelectedCity);
hashMap.put("type",mUserType);
} catch (JSONException e) {
e.printStackTrace();
}
Call<ResponseBody> call = apiInterface.registerUser(hashMap);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.hide();
try {
JSONObject jsonObject = new JSONObject(response.body().toString());
Log.e("SignupFragment", jsonObject.toString());
if (response.code() == 200) {
Toast.makeText(RegistrationActivity.this, "Success",Toast.LENGTH_SHORT).show();
/*Intent intent = new Intent(RegistrationActivity.this, LoginActivity.class);
startActivity(intent);
finishAffinity();*/
} else {
Toast.makeText(RegistrationActivity.this, "Failed",Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progressDialog.hide();
call.cancel();
Toast.makeText(RegistrationActivity.this, "Failed",Toast.LENGTH_SHORT).show();
}
});
}
Should i need to changes my interface or there may be some error in my api call?
Thanks in andvance
The issue is with your locationPost type, it should be JsonObject and not JSONObject, so try one of the following approaches
Approach 1
Api Interface
Call<ResponseBody> registerUser(#Body JsonObject locationPost);
Api call
JsonObject obj = new JsonObject();
obj.addProperty("httpMethod","POST");
obj.addProperty("firstname",firstNameValue);
// add the rest of the field
Call<ResponseBody> call = apiInterface.registerUser(obj);
//rest of the logic remains same
Approach 2
create a POJO class representing the object and pass the instance of the object
public class RequestObject{
final String httpMethod, firstname;
// declare member variables for all the keys
RequestObject(String method,String firstname){
this.httpMethod = method;
this.firstname = firstname;
}
}
API Interface
Call<ResponseBody> registerUser(#Body RequestObject locationPost);
Api call
RequestObject requestobject = new RequestObject("POST","firstName");
// add the rest of the field
Call<ResponseBody> call = apiInterface.registerUser(requestObject);
//rest of the logic remains same
I think you have to re-check these parameters carefully.
{
"httpMethod": "POST",
"firstname": "Ali",
"lastname": "Patel",
"email": "alipatel05#gmail.com",
"password": "12345678",
"country": "Canada",
"state": "Quebec",
"city": "Montreal",
"type": "Parent"
}

Convert HashMap to Associative Array Android Retrofit Laravel

I am using Retrofit To Pass HashMap to Laravel Restful API. I need help to catch this hashmap and convert it to an associative array so I can loop through and insert into MySql database. Please see the code below.
Android
#FormUrlEncoded
#POST("create_phone_contacts")
Call<ResponseBody> createPhoneContacts(
#Field("id") String id,
#FieldMap Map<String, String> phoneContactPhones,
#FieldMap Map<String, String> phoneContactEmails
);
Laravel
class CreatePhoneContactsController extends Controller
{
public function create(Request $request)
{
$phoneContactsPhones = new PhoneContactsPhonesModel;
$phoneContactsPhones->mysql_user_id = $request->id;
$phoneContactsPhones->phone = $request->phone;
$phoneContactsPhones->name = $request->name;
$phoneContactsPhones->save();
$phoneContactsEmails = new PhoneContactsEmailsModel;
$phoneContactsEmails->mysql_user_id = $request->id;
$phoneContactsEmails->email = $request->email;
$phoneContactsEmails->name = $request->name;
$phoneContactsEmails->save();
if ($phoneContactsPhones->save() && $phoneContactsEmails->save()) {
return ['success' => 'Phone Contacts Created'];
} else {
return ['failure' => 'Phone Contacts Failure'];
}
}
}
Here I am just catching the fields, how should I catch the hashmap in Laravel and convert it into associative array... thanks....
This is working now, it will take the map send it via retrofit and insert into mysql.
Activity
Call<JsonObject> call = RetrofitMySql
.getInstance()
.getApi()
.createPhoneContacts(mySqlUserId,
namePhoneMap);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call,
Response<JsonObject> response) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(new Gson().toJson(response.body()));
Log.d("",
"JsonReturned: " + jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<JsonObject> call,
Throwable t) {
Log.d("response",
"Getting response from server : " + t);
}
});
API
#POST("create_phone_contacts/{id}")
Call<JsonObject> createPhoneContacts(
#Path("id") String id,
#Body Map<String, String> namePhoneMap
);
Laravel
public function create(Request $request, $id)
{
$json = json_decode($request->getContent(), true);
foreach ($json as $key => $value) {
$users = new PhoneContactsPhonesModel;// ---> here
$users->mysql_user_id = $id;
$users->phone = $key;
$users->name = $value;
$users->save();
}
}

Login with retrofit in android

I am trying to use login api via retrofit. I need to send only mobile number. When i am using postman body it is getting an output. but when iam calling with android its getting an error json like below
{
"error": "Validation error",
"error_code": "001",
"Validation_errors": {
"mobile": "<p>The Mobile field is required.</p>"
}
}
HomeActivity.class
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Map<String,String> user = new HashMap<>();
user.put("mobile",username.getText().toString().trim());
Call<ResponseBody> mService = apiService.loginwithno(user);
Log.d("TAG", "response: " + mService.toString());
mService.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
String result = response.body().string();
JSONObject mJsonObject = new JSONObject(result);
Log.d("TAG", "response: " + mJsonObject.toString());
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
buttonVisible();
username.setError("Please try again");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
call.cancel();
buttonVisible();
Snackbar snackbar = Snackbar.make(buttonLogin,
"Please check your internet connection", Snackbar.LENGTH_LONG);
snackbar.show();
}
ApiClient
public class ApiClient {
public static final String BASE_URL = "http://nast.in/driverpool/api/index.php/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
ApiInterface
public interface ApiInterface {
#POST("account/login?")
Call<ResponseBody> loginwithno(#Body Map<String, String> mobile);
#POST("account/verifyotp")
Call<ResponseBody> verifyotp(#Body HashMap<String, String> mobile);//Param name: mobile, otp
#POST("account/resendotp")
Call<ResponseBody> resentotp(#Body HashMap<String, String> mobile);
}
Postman screenshot
First you don't need '?' in your api and i think you must send json in your #body so create class like this
public class SendLoginData{
#SerializedName("mobile")
public String mobile;
public SendLoginData(String mobile) {
this.mobile = mobile;
}
}
And use it in ApiInterface
#POST("account/login")
Call<ResponseBody> loginwithno(#Body SendLoginData post);
You need to make few changes in code.
Change your login api to receive json like this, include gson library if you have not added in project.
#POST("account/login?")
Call loginwithno(#Body Map mobile);
Create an ApiErrorResponse object to handle your api error. Add getter, setter and #SerializedName as required.
class ApiErrorResponse{
String error;
String error_code;
ValidationErrors Validation_errors;
}
class ValidationErrors{
String mobile;
}
on API error handle like this
if(!response.isSuccessful()){
Converter converter =
ApiClient.getClient().responseBodyConverter(ApiErrorResponse.class, new Annotation[0]);
ApiErrorResponse errors = null;
try {
errors = converter.convert(response.errorBody());
} catch (Exception e) {
}
if(errors!=null){
//Handle your API Error logic here
}
}

Access sent parameter in onResponse of retrofit 2

I create a request with retrofit2 and send parameter to server, how can access sent parameter in onResponse?
retrofit = new Retrofit.Builder()
.baseUrl("baseAddress")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiBase serviceSetParam = retrofit.create(ApiBase.class);
Call<String> myCall = serviceSetParam.setParam("data1","data2");
Callback<String> myCallback = new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
//i need access data1 & data2 Here !
if (response.isSuccessful()) {
String mResponse= response.body();
} else {
Utils.Log("unSuccessful");
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Utils.Log("onFailure");
}
};
myCall.enqueue(myCallback);
here the send param method:
#FormUrlEncoded
#POST("set")
Call<String> setParam(#Field("param1") String param1, #Field("param2") String param2);
in onResponse method of your request, test this code:
try {
BufferedSink bf = new Buffer();
call.request().body().writeTo(bf);
Log.i("params are",bf.buffer().readUtf8().toString());
} catch (IOException e) {
e.printStackTrace();
}
You need to get the original Request from OkHttp.
List<String> pathSegments = original(response.raw()).url().pathSegments();
given:
static Request original(Response response) {
while (true) {
Response prior = response.priorResponse();
if (prior == null) {
break;
}
response = prior;
}
return response.request();
}

Categories

Resources