A method build in Java using Jersey which takes two parameters and store in database it works properly with the postman but when I use it in Android Application it not work. I try to send a request using Volley and Retrofit.
Server Side Code:
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("/register")
public Boolean registerUser(#FormParam("userName") String userName, #FormParam("password") String password) {
System.out.println(userName+"\t"+password);
String insertQuery = "INSERT INTO user(user_name,password,status) VALUES(?,?,?)";
try {
Connection con = MyConnection.getConnection();
PreparedStatement prst = con.prepareStatement(insertQuery);
prst.setString(1, userName);
prst.setString(2, password);
prst.setInt(3, 0);
int count = prst.executeUpdate();
con.close();
System.out.println(count+" Row inserted");
return true;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
Android Code :
public void register(final String userName, final String password) {
User user = new User(userName, password, 1);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.13:8080/Demo_Application/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceholderApi jsonPlaceholderApi = retrofit.create(JsonPlaceholderApi.class);
Call<List<User>> call = jsonPlaceholderApi.register("application/x-www-form-urlencoded", user);
call.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
if (!response.isSuccessful()){
Log.e("Response","Something went wrong."+response.toString());
return;
}
Log.d("Response",response.toString());
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Log.e("Response",t.getMessage());
}
});
}
Postman Response
Volley Request:
public void registerVolley(final String userName, final String password){
Map<String, String> param = new HashMap<>();
param.put("userName", userName);
param.put("password",password);
JsonObjectRequest arrayRequest = new JsonObjectRequest(Request.Method.POST, "http://192.168.0.26:8080/Demo_Application/rs/test/register", new JSONObject(param), new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("Response", response.toString());
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Response", error.toString());
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> param = new HashMap<>();
param.put("userName", userName);
param.put("password",password);
return param;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> header = new HashMap<>();
header.put("Content-Type","application/json");
return header;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(arrayRequest);
}
Your code for retrofit:
JsonPlaceholderApi jsonPlaceholderApi = retrofit.create(JsonPlaceholderApi.class);
Call<Boolean> call = jsonPlaceholderApi.sign("userName", "password");
call.enqueue(new Callback<Boolean>() {
#Override
public void onResponse(Call<Boolean> call, Response<Boolean> response) {
if (!response.isSuccessful()){
Log.e("Response","Something went wrong."+response.toString());
return;
}
Log.d("Response",response.toString());
}
#Override
public void onFailure(Call<Boolean> call, Throwable t) {
Log.e("Response",t.getMessage());
}
});
Your method inside jsonPlaceholderApi :
#FormUrlEncoded
#POST("rs/test/register")
Call<ResponseLogin> signIn(
#Field("userName") String userName,
#Field("password") String password
);
Add Below Code in proguard-rules.pro
-keepattributes *Annotation*
-keepclassmembers class ** {
#org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keep class com.app.appname.model.** { *; }
NOTE: Change last line with your model folder
Related
I want to send a DELETE request to an API to delete a city with the given id. In the API request documentation it says that the DELETE request requires as parameters the authentication token and the city id. When I run the code below I always get a com.android.volley.AuthFailureError.
Here's my code:
void deleteCity(String cityId, final VolleyResponseListener volleyResponseListener){
String url = baseUrl + "city";
try {
JSONObject params = new JSONObject();
params.put("token", token);
params.put("city_id", cityId);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.DELETE, url, params, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try{
String success = response.get("success").toString();
if(success.equals("true")){
volleyResponseListener.onResponse();
}else{
String errorMessage = response.get("errorMessage").toString();
throw new Exception(errorMessage);
}
} catch (Exception e) {
volleyResponseListener.onError(e.getMessage());
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
volleyResponseListener.onError("Volley Error");
}
});
requestQueue.add(jsonObjectRequest);
}catch (JSONException e){
volleyResponseListener.onError("Param error");
}
}
UPDATE:
I solved the problem by adding the city id as a query in the HTTP request and sent the authentication token in the header. Here is the final code:
void deleteCity(String cityId, final VolleyResponseListener volleyResponseListener){
String url = baseUrl + "city?city_id="+cityId;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.DELETE, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try{
String success = response.get("success").toString();
if(success.equals("true")){
volleyResponseListener.onResponse();
}else{
String errorMessage = response.get("errorMessage").toString();
throw new Exception(errorMessage);
}
} catch (Exception e) {
volleyResponseListener.onError(e.getMessage());
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
volleyResponseListener.onError("Volley Error");
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
headers.put("token", token);
return headers;
}
};
requestQueue.add(jsonObjectRequest);
}
I sent request with postman its working, but volley doesn't work. I always get error! I searched stackoverflow volley returns error when response is empty but i added CustomJsonObjectRequest still the issue remains.
Error message
Volley org.json.JSONException: End of input at character 0 of
CustomJsonObjectRequest
public class CustomJsonObjectRequest extends JsonObjectRequest {
public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, jsonRequest, listener, errorListener);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
if (response.data.length == 0) {
byte[] responseData = "{}".getBytes("UTF8");
response = new NetworkResponse(response.statusCode, responseData, response.headers, response.notModified);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.parseNetworkResponse(response);
}
}
Volley request
EcoElement ecoElement = ecoElementArrayList.get(position);
Map<String, String> params = new HashMap<String, String>();
params.put("Id", ecoElement.getId().toString());
params.put("Checked", ecoElement.getChecked().toString());
JSONObject ObjParams = new JSONObject(params);
try {
CustomJsonObjectRequest getRequest = new CustomJsonObjectRequest(Request.Method.PUT, "https://ourwebsite.sslbeta.de/api/gardenapi/updateecoelements", ObjParams,
response -> {
Toast.makeText(getContext(), ""+response, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
},
error -> {
Toast.makeText(getContext(), ""+error.toString(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
);
RequestQueueSingleton.getInstance(getContext()).addToRequestQueue(getRequest);
} catch (Exception e) {
Toast.makeText(getContext(), e.toString(), Toast.LENGTH_LONG).show();
}
Finally i was able to fix the issues after hours of searching. There were two reasons to this, first is that api was returning null/empty so CustomJsonObjectRequest fixed that, and then another issue is that i forgot to add authentication headers. that was a silly mistake i know!
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer "+access_token);
return headers;
}
};
Here is the solution, just create this method and pass your value.
private void CustomJsonObjectRequest() {
String tag_string_req = "req__details";
StringRequest strReq = new StringRequest(Request.Method.POST, <API URL>, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
getPerspective().showErrorLogs(TAG, "Response Invest : " + response);
try {
// Parse your response here
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("Id", <ID VALUE HERE>);
params.put("Checked", <TRUE or FALSE>);
return params;
}
};
strReq.setRetryPolicy(new RetryPolicy() {
#Override
public void retry(VolleyError arg0) throws VolleyError {
}
#Override
public int getCurrentTimeout() {
return 0;
}
#Override
public int getCurrentRetryCount() {
return 0;
}
});
strReq.setShouldCache(false);
addToRequestQueue(strReq, tag_string_req);
}
Both ID and Checked must have String type.And create below methods in MainActivity:
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
In my app I have a spinner that includes some language abbreviation example (en, az, and others), I want to set selected language abbreviation as the request header and I need this in every request so I am saving abbreviation in shared preferences and get abbreviation in my ApiClient class,
every time that spinner selection has changed I change shared preferences abbreviation value but header only set the first time I select a language and when I change spinner selection header not change
This is my ApiClient class
private static final String BASE_URL = ApiUrls.server_url;
public static Retrofit getClient(Context context)
{
SharedPrefUtil sharedPrefUtil = new SharedPrefUtil(context);
String locale = sharedPrefUtil.getSelectedLanguage();
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient = httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException
{
Request request = chain.request().newBuilder().header("Accept-Language",
locale).build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).client(httpClient.build())
.build();
return retrofit;
}
This is my ApiRequester class method for sending a request to server
public static void sendLogin(final Context context, Map<String, String> params,
final HttpResponses.onLoginSuccess onLoginSuccess) {
DialogHelper.ProgressDialog progressDialog = showWaitDialog(context);
if (hasInternetConnection(context)) {
params.put("grant_type", "password");
params.put("client_id", "raymon-client");
params.put("client_secret", "raymon-secret");
ApiInterface apiService = ApiClient.getClient(context).create(ApiInterface.class);
Call<ResponseBody> call = apiService.loginRequest(params);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.dismiss();
//result ok
if (response.code() == 200)
{
try
{
onLoginSuccess.loginResponse(JsonSuccessParser.parseLoginResponse
(context, response.body().string()));
} catch (IOException e)
{
e.printStackTrace();
}
}
else if (response.code() == 403)
{
onLoginSuccess.loginError(response.code());
}
else
{
try
{
JsonErrorParser.parseServerError(context,response.errorBody().string());
} catch (IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progressDialog.dismiss();
showNoConnectionDialog(context);
}
});
} else {
progressDialog.dismiss();
showNoConnectionDialog(context);
}
}
This is my code for setting language abbreviation in shared preferences
private void setUserLocale()
{
String selected_country = countryCodeAdapter.getItem(country_code_spinner.
getSelectedItemPosition()).language.abbreviation.toLowerCase();
LocaleHelper.setLocale(this,selected_country);
}
How can I change header immediately when user change spinner position?
In ApiClient class, you should initialize locale variable inside of interceptor methods to reflect your changes.
Example)
private static final String BASE_URL = ApiUrls.server_url;
public static Retrofit getClient(Context context)
{
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient = httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException
{
SharedPrefUtil sharedPrefUtil = new SharedPrefUtil(context);
String locale = sharedPrefUtil.getSelectedLanguage();
Request request = chain.request().newBuilder().header("Accept-Language",
locale).build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).client(httpClient.build())
.build();
return retrofit;
}
However, if the value changes constantly, it may be possible to explicitly pass the value of the Header as an argument to the Service instead of the Interceptor.
Example)
public interface ApiService {
Call<...> loginRequest(#Header("Accept-Language") String language, #QueryMap Map<String, String> params);
}
public static void sendLogin(final Context context, Map<String, String> params,
final HttpResponses.onLoginSuccess onLoginSuccess) {
DialogHelper.ProgressDialog progressDialog = showWaitDialog(context);
if (hasInternetConnection(context)) {
params.put("grant_type", "password");
params.put("client_id", "raymon-client");
params.put("client_secret", "raymon-secret");
SharedPrefUtil sharedPrefUtil = new SharedPrefUtil(context);
String locale = sharedPrefUtil.getSelectedLanguage();
ApiInterface apiService = ApiClient.getClient(context).create(ApiInterface.class);
Call<ResponseBody> call = apiService.loginRequest(locale, params);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.dismiss();
//result ok
if (response.code() == 200)
{
try
{
onLoginSuccess.loginResponse(JsonSuccessParser.parseLoginResponse
(context, response.body().string()));
} catch (IOException e)
{
e.printStackTrace();
}
}
else if (response.code() == 403)
{
onLoginSuccess.loginError(response.code());
}
else
{
try
{
JsonErrorParser.parseServerError(context,response.errorBody().string());
} catch (IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progressDialog.dismiss();
showNoConnectionDialog(context);
}
});
} else {
progressDialog.dismiss();
showNoConnectionDialog(context);
}
}
I am trying to retrieve data from server using volley, but when I call this method the first time, I get the response from server, but null is returned by the method. If I call it the second time I get the last response.
public String retrieveDataFromServer(String url, String param, final String token){
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
data = new JSONObject(response).toString();
}catch (Exception e){}
//Toast.makeText(getApplicationContext(), "wow" + data, Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try{
data = new JSONObject(error.toString()).toString();
}catch (Exception e){}
//Toast.makeText(getApplicationContext(), "" +data, Toast.LENGTH_SHORT).show();
}
}) {
/**
* Passing some request headers
*/
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
String bearer = "Bearer ".concat(token);
Map<String, String> headersSys = super.getHeaders();
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
//headers.put("token", token);
headersSys.remove("Authorization");
headers.put("Authorization", bearer);
headers.putAll(headersSys);
return headers;
}
};
// Adding request to request queue
addToRequestQueue(stringRequest);
//Toast.makeText(getApplicationContext(), "wow" + data, Toast.LENGTH_SHORT).show();
return data;
}
How do I get the response on first call of method?
You can use call back to return Volley response:
public void retrieveDataFromServer(final VolleyCallback callback) {
StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.onSuccess(response);
}
}
}}
Create interface:
public interface VolleyCallback{
void onSuccess(String response);
}
And get result from activity:
String yourString = "";
#override
public void onResume() {
super.onResume();
retrieveDataFromServer(new VolleyCallback(){
#Override
public void onSuccess(String response){
//Get result from here
yourString = response;
}
});
}
I want to send a POST RAW data of {"userid": "userid","pass":"1222"} as a user name and password. I have one layout consisting of username and password that will fetch as userid and password. I need help in trying this to retrofit
// Triggers when LOGIN Button clicked
public void checkLogin(View arg0) {
// Initialize AsyncLogin() class with userid and password
new REST().execute();
}
public class REST extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// The Username & Password
final EditText usr = (EditText) findViewById(R.id.username);
userid = (String) usr.getText().toString();
final EditText pw = (EditText) findViewById(R.id.password);
password = (String) pw.getText().toString();
}
#Override
protected Void doInBackground(Void... params) {
HttpURLConnection urlConnection=null;
String json = null;
// -----------------------
try {
HttpResponse response;
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("username", usr);
jsonObject.accumulate("password", password);
json = jsonObject.toString();
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://mark.journeytech.com.ph/mobile_api/authentication.php");
httpPost.setEntity(new StringEntity(json, "UTF-8"));
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Accept-Encoding", "application/json");
httpPost.setHeader("Accept-Language", "en-US");
response = httpClient.execute(httpPost);
String sresponse = response.getEntity().toString();
Log.w("QueingSystem", sresponse);
Log.w("QueingSystem", EntityUtils.toString(response.getEntity()));
}
catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
} finally {
// nothing to do here
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(getApplicationContext(), email + " "+ password, Toast.LENGTH_SHORT).show();
if (result != null) {
// do something
} else {
// error occured
}
}
please any help because i searched a lot and didn't reach anything
You need to follow following steps :
Network API interface
public interface NetworkAPI {
#GET("authentication.php")
#Headers({"Content-Type:application/json; charset=UTF-8"})
Call<JsonElement> loginRequest(#Body LoginRequest body);
}
Login Request model class
public class LoginRequest {
String userid;
String password;
public LoginRequest(String userid, String password) {
this. userid = userid;
this. pass = pass;
}
}
Retrofit call in your activity
String baseUrl ="http://mark.journeytech.com.ph/mobile_api/";
NetworkAPI networkAPI;
public void loginRequest(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
networkAPI = retrofit.create(NetworkAPI.class);
LoginRequest loginRequest = new LoginRequest(yourusername,yourpassword);
Call<JsonElement> call = networkAPI.loginRequest(loginRequest);
call.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
// success response
}
#Override
public void onFailure(Call<JsonElement> call, Throwable t) {
// failure response
}
});
}
First: you should create your api interface
public interface Api
{
#Headers({"Accept: application/json"})
#FormUrlEncoded
#POST("authentication.php")
Call<Void> Login(#Field("[email]") String email,
#Field("[password]") String password);
}
Second: In your activity you should call your function
void Login(String email, final String password)
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://mark.journeytech.com.ph/mobile_api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Apiservice = retrofit.create(Api.class);
Call<Void> call = service.Login(email, password);
call.enqueue(new Callback<Void>()
{
#Override
public void onResponse(Call<Void> call, Response<Void> response)
{
if (response.isSuccess())
{
}
else
{
}
}
#Override
public void onFailure(Call<Void> call, Throwable t)
{
}
});
}