I need to post an array of attendees as shown in the image above. I tried using Hashmap but it gives some errors and I don't know if it is server-side error or retrofit.
Here is my code :
API interface
#FormUrlEncoded
#POST("vendor/event/{id}/checkin")
Call<DefaultResponse> updateAttendance(
#Path("id") int id,
#QueryMap Map<String,String> attendees,
#Field("token") String token);
Response class
String message;
public DefaultResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
And here is the code of my Activity
final Map<String,String> attendees = new HashMap<>();
for (int i = 0; i < attendeesTables.size(); i++){
attendees.put("id", String.valueOf(attendeesTables.get(i).getId()));
attendees.put("arrival_time",
attendeesTables.get(i).getArrival_time());
}
if (attendeesTables.size() > 0) {
Call<DefaultResponse> call = RetrofitClient.getmInstance().getApi().updateAttendance(event_id,attendees,token);
call.enqueue(new Callback<DefaultResponse>() {
#Override
public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) {
Toast.makeText(EventsDetailsActivity.this, response.code()+"", Toast.LENGTH_SHORT).show();
Toast.makeText(EventsDetailsActivity.this, response.isSuccessful()+"", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<DefaultResponse> call, Throwable t) {
Toast.makeText(EventsDetailsActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Am I doing everything in the right way?
I get request code 400(bad request)
You params are not correct that's why you getting 400 error. try like below
Request :
#FormUrlEncoded
#POST("vendor/event/{id}/checkin")
Call<DefaultResponse> updateAttendance(
#Path("id") int id,
#Field("attendees") String attendees,
#Field("token") String token);
Api Call :
JSONArray attendeesArray=new JSONArray();
for (int i = 0; i < attendeesTables.size(); i++){
JSONObject jsonObject=new JSONObject();
jsonObject.put("id",String.valueOf(attendeesTables.get(i).getId()));
jsonObject.put("arrival_time",String.valueOf(attendeesTables.get(i).getArrival_time()));
attendeesArray.put(jsonObject);
}
if (attendeesTables.size() > 0) {
Call<DefaultResponse> call = RetrofitClient.getmInstance().getApi().updateAttendance(event_id,attendeesArray.toString(),token);
call.enqueue(new Callback<DefaultResponse>() {
#Override
public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) {
Toast.makeText(EventsDetailsActivity.this, response.code()+"", Toast.LENGTH_SHORT).show();
Toast.makeText(EventsDetailsActivity.this, response.isSuccessful()+"", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<DefaultResponse> call, Throwable t) {
Toast.makeText(EventsDetailsActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
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 need to send list of below objects on retrofit , but always I receive error , your body is null
{
"height": "20",
"weight": "40",
"unit": "kg"
}
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<ResponseBody> call = service.getAllPhotos("");
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.v("SUCCESS", response.body() + " ");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
First you have to create your models use click here
Your model will be like this
public class User {
#SerializedName("height")
#Expose
private String height;
#SerializedName("weight")
#Expose
private String weight;
#SerializedName("unit")
#Expose
private String unit;
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
}
On your API interface create this method
#POST("/service name for example register")
Call<ResponseBody> postUsers(#Body List<User> userRequest);
On Main Activity use below code
public void postUsers(List<Users> userRequest) {
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<ResponseBody> call = service.postUsers(userRequest);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.v("SUCCESS", response.body() + " ");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
}
I want to post user credentials to following url
: http://myurl/authenticate
Parameters : login. Type (JSON)
username : string
password : string
"login":{"username": "JohnDoe","password": "eoDnhoJ" }
If success
{
" r e s u l t " : " S u c c e s s " ,
"response": "Users Session ID"
}
Here is my code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
public class ApiUtils {
private ApiUtils() {}
public static final String BASE_URL = "http://myurl/";
public static APIService getAPIService() {
return RetrofitClient.getClient(BASE_URL).create(APIService.class);
}
}
public class Login {
#SerializedName("username")
#Expose
private String username;
#SerializedName("password")
#Expose
private String password;
//getters and setters
}
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public class LoginActivity extends AppCompatActivity {
private EditText usernameEditText,passwordEditText;
private Button button;
private APIService mAPIService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText=(EditText)findViewById(R.id.username);
passwordEditText=(EditText)findViewById(R.id.password);
button=(Button)findViewById(R.id.signup);
mAPIService = ApiUtils.getAPIService();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String uname=usernameEditText.getText().toString();
String pass=passwordEditText.getText().toString();
if(TextUtils.isEmpty(uname)){
Toast.makeText(LoginActivity.this, "Username cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(TextUtils.isEmpty(pass)){
Toast.makeText(LoginActivity.this, "Password cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(pass.length()<4){
Toast.makeText(LoginActivity.this, "Password should be greater than four characters", Toast.LENGTH_SHORT).show();
return;
}
sendPost(uname, new StringBuilder(uname).reverse().toString());
}
});
}
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
public void showResponse(String response) {
Log.i("Abbu",response);
}
}
Whenever i submit username and password i get null values,can some body please help me?And how can iget the sessionId.I tried looking for various egs but i am so confsued right now.
Instead of follwing code
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
Use this code
#POST("/authenticate")
Call<Login> savePost(#Query("username") String username,
#Query("password") String password);
Step 1: instead of this code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
Use this code:
public interface APIService {
#POST("/authenticate")
Call<Login> savePost(#Body RequestBody body);
}
Step 2: instead of this code in LoginActivity
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Change to this code :
public void sendPost(String username, String password) {
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
String strRequestBody = new Gson().toJson(params);
//create requestbody
final RequestBody requestBody = RequestBody.create(MediaType.
parse("application/json"),strRequestBody);
mAPIService.savePost(requestBody).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Replace your Login class by following
#SerializedName("result")
#Expose
private String rESULT;
#SerializedName("response")
#Expose
private String response;
public String getRESULT() {
return rESULT;
}
public void setRESULT(String rESULT) {
this.rESULT = rESULT;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
Add ServiceGenerator class :
public class ServiceGenerator {
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(ScalarsConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
public static Retrofit getRetrofit()
{
return builder.client(httpClient.build()).build();
}
}
2.Add interface RetrofitAPI :
public interface RetrofitApi {
#POST("/api/v1/user")
Call<ResponseBody> login(#Body RequestBody loginBody);
}
3.Add method for login in your manager class :
public void retrofitLogin(JSONObject login, final String tag) {
RetrofitApi service = ServiceGenerator.createService(RetrofitApi.class);
Call<ResponseBody> result = service.login(convertJsonToRequestBody(login));
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
retrofitCheckResponse(response, tag);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof IOException) {
Log.e("retrofit error", "retrofit error");
sendErrorRetrofit(mContext.getString(R.string.ERROR), 500, tag);
}
}
});
}
Method to convert JSONObject to RequestBody :
private RequestBody convertJsonToRequestBody(JSONObject jsonObject) {
if (jsonObject != null) {
return RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonObject.toString());
} else {
return null;
}
}
4.Now call your retrofitLogin method :
JSONObject mLoginParams = new JSONObject();
JSONObject mLoginObj = new JSONObject();
mLoginParams.put("username", uname);
mLoginParams.put("password", pass);
mLoginObj.put("appType","mobile");
mLoginObj.put("user", mLoginParams);
volleyRequest.retrofitLogin(mLoginObj, "Login");
//get user and password form JSONArray
public void loginapi(){
String username = user.getText().toString();
String password = passwd.getText().toString();
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<Akses>> call = apiService.getEmployeeAkses(donat, username, password);
call.enqueue(new Callback<List<Akses>>() {
#Override
public void onResponse(Call<List<Akses>> call, Response<List<Akses>> response) {
String waduser,wadpass;
ArrayList<Akses> aksesList = new ArrayList<Akses>();
waduser = aksesList.get(0).getUsername().toString();
wadpass = aksesList.get(0).getPassword().toString();
}
#Override
public void onFailure(Call<List<Akses>> call, Throwable t) {
Log.e("Errore : ", t.getMessage());
Toast.makeText(getApplicationContext(), "Terjadi Kesalahan masalah API", Toast.LENGTH_SHORT);
}
});
}
How to get JSONArray with the code ?
waduser = aksesList.get(0).getUsername().toString();
wadpass = aksesList.get(0).getPassword().toString();
when the above code is logged, it does not produce anything.
what should i do ?
try this
public void loginapi(){
String username = user.getText().toString();
String password = passwd.getText().toString();
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<Akses>> call = apiService.getEmployeeAkses(donat, username, password);
call.enqueue(new Callback<List<Akses>>() {
#Override
public void onResponse(Call<List<Akses>> call, Response<List<Akses>> response) {
String waduser,wadpass;
// you should use (ArrayList<Akses>) response.body;
ArrayList<Akses> aksesList = (ArrayList<Akses>) response.body;
waduser = aksesList.get(0).getUsername().toString();
wadpass = aksesList.get(0).getPassword().toString();
}
#Override
public void onFailure(Call<List<Akses>> call, Throwable t) {
Log.e("Errore : ", t.getMessage());
Toast.makeText(getApplicationContext(), "Terjadi Kesalahan masalah API", Toast.LENGTH_SHORT);
}
});
}
I'm working on Retrofit 2.0 (which is awesome) to handle API responses.
All works well when API answers with success, I return the converted object wished from the json response
Here an example of request:
ServiceAPI.getUser(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
User user = response.body(); // user is my POJO
}
#Override
public void onFailure(Call<User> call, final Throwable t) {
Log.e(TAG, "Error: " + t.getMessage())
}
});
When response is done, I return the POJO (which is my main purpose), not the json to parse in order to avoid boilerplate.
So here my code to handle this :
// the interface to handle calls
protected interface ServiceAPI {
#GET("/user/{userId}")
Call<User> getUser(#Path("userId") String userId);
}
// the GSON part for converting data
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new ItemTypeAdapterFactory())
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
// an interceptor to log requests responses
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(new LogJsonInterceptor())
.build();
// the retrofit builder
retrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl)
.client(okClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
// the interceptor to log requests
public static class LogJsonInterceptor implements Interceptor {
#Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
String rawJson = response.body().string();
Log.d(TAG, rawJson);
// Re-create the response before returning it because body can be read only once
return response.newBuilder().body(ResponseBody.create(response.body().contentType(), rawJson)).build();
}
}
// here the magic to handle json response and get data from "data" json key
public static class ItemTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
private RestError error;
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("data")) {
jsonElement = jsonObject.get("data");
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
// here the method to call from an activity for example to get an User
public static void getUser(final String userId, final Callback<User> callback) {
serviceAPI.getUser(userId).enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
callback.onResponse(call, response);
}
#Override
public void onFailure(Call<User> call, Throwable t) {
callback.onFailure(call, t);
}
});
}
// here the call from the Activity
ServiceAPI.getUser(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
User user = response.body();
}
#Override
public void onFailure(Call<User> call, final Throwable t) {
Log.e(TAG, "Error: " + t.getMessage())
}
});
// when API answers with success (code 200 from headers)
{
"data":
{
"id":1,
"name":"myname",
"email":"myemail"
}
}
So all works well here because I get response from "data" and convert the response into my POJO
PROBLEM:
But when API answers with an error (also with code 200 from headers), I get this:
{
"error":
{
"code":200
"type":"OAuth_exception",
"message":"You need an access token to get an user",
}
}
The problem is that the retrofit "response" is nevertheless successfull and the errorBody is null
So here, I would to convert this into a RestError POJO (below) and send it inside the call when calling getUser method
public class RestError {
private int code;
private String message;
private String type;
public RestError(int code, String message, String type) {
this.code = code;
this.message = message;
this.type = type;
}
}
Any idea to fix that?
UPDATE:
I added this in the ItemTypeAdatperFactory
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("data")) {
jsonElement = jsonObject.get("data");
} else if (jsonObject.has("error")) {
jsonElement = jsonObject.get("error");
TypeAdapter<RestError> restErrorTypeAdapter = gson.getAdapter(RestError.class);
RestError error = restErrorTypeAdapter.fromJsonTree(jsonElement);
return (T) error;
}
}
return delegate.fromJsonTree(jsonElement);
}
And I created a custom Callback like this:
public abstract static class CustomCallback<T> implements Callback<T> {
public abstract void onError(RestError error);
public abstract void onSuccess(T body);
#Override
public void onResponse(Call<T> call, Response<T> response) {
if(response.body() instanceof RestError) {
onError((RestError) response.body());
} else {
onSuccess(response.body());
}
}
#Override
public void onFailure(Call<T> call, Throwable t) {
Log.e(TAG, t.toString());
}
}
So now how the call is:
ServiceAPI.getUser(new ServiceAPI.CustomCallback<User>() {
#Override
public void onError(RestError error) {
Log.e(TAG, error.toString());
}
#Override
public void onSuccess(User body) {
Log.d(TAG, body.toString());
User user = body;
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
So now when an error occurs I get it from onError(), otherwise onSuccess() and seems to do the job
What do you think about?
You can extend all your POJOs from some Response class, which will contain field RestError error. Then you can make some isSuccessful method, which will check is error field null or not and handle it properly.
In my view, you can customize your ItemTypeAdapterFactory like that to check if the reponse is your data or it is an error
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("data")) {
jsonElement = jsonObject.get("data");
} else if(jsonObject.has("error"){
jsonElement = jsonObject.get("error");
}
}
//TODO: need to handle your parsing here (to data or to error)
return delegate.fromJsonTree(jsonElement);
}