I am new to android and using volley to communicate with web services.
Postman details
I found sending a raw text to the web service will only work on postman.I try using grant_type=password&username=myusername&password=mypassowrd getting myusername and mypassword from two editText from my mainActivity, .
Is there any better way to achieve this?
public class MainActivity extends AppCompatActivity {
Button btnLogin,btnFetch,btnExit;
EditText editTxtUsr,editTxtPass;
TextView txtView;
String uRL ="****";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLogin=findViewById(R.id.buttonLogin);
btnFetch=findViewById(R.id.buttonFetch);
btnExit=findViewById(R.id.buttonExit);
editTxtUsr=findViewById(R.id.editTextUsrname);
editTxtPass=findViewById(R.id.editTextPassword);
txtView=findViewById(R.id.textViewData);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String wsURL = uRL + "/authtoken";
//final String appData = "grant_type=password&username=" + editTxtUsr + "&password=" + editTxtPass;
StringRequest request = new StringRequest(Request.Method.POST, wsURL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.equals("true")) {
Toast.makeText(MainActivity.this, "Login Successful", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Incorrect ", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(MainActivity.this, "Some error occured" + volleyError, Toast.LENGTH_SHORT).show();
}
}) {
#Override
public Map<String,String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/text");
headers.put("charset", "TYPE_UTF8_CHARSET");
return headers;
}
#Override
protected Map<String,String> getParams() throws AuthFailureError {
Map<String, String> parameters = new HashMap<>();
parameters.put("grand_type", "SET_VALUE");
parameters.put("Username", editTxtUsr.getText().toString());
parameters.put("Password", editTxtPass.getText().toString());
return parameters;
}
};
RequestQueue rQueue= Volley.newRequestQueue(MainActivity.this);
rQueue.add(request);
}
});
btnExit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
}
}
I have tried various ways to achieve this, but with no luck. That's a sample of my code that I use to try to connect to the web service.
I get [253] BasicNetwork.performRequest: Unexpected response code 400 for...
I searched thoroughly through StackOverflow but I can't seem to find the correct answer to my question.
Any help would be appreciated.
Its been days I have been working on this but after I posted my question, I found the solution after some tries.
The answer is simpler than I have thought.
What you need to do is make an objectrequest and override the body with the text you want to post. Nothing had to change in headers or parameters.
I still can't find an answer using Stringrequest.
#Override
public byte[] getBody() {
try {
return requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
Where requestBody is the raw text you want to send as a string.
Related
I'm working on an Android app and currently stuck to link my database to my app for registration using volley but I get the problem:
this is response:
com.android.volley.NoConnectionError:java.io.IOEXCEPTION: Cleartext HTTP traffic to 10.0.2.2 not permitted
Here is my MainActivity code:
public class MainActivity extends AppCompatActivity {
Button loginBtn;
EditText password, username;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
password = findViewById(R.id.pssword);
username = findViewById(R.id.username);
loginBtn = findViewById(R.id.check);
loginBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
}
});
}
void login() {
StringRequest request = new StringRequest(Request.Method.POST,
"http://10.0.2.2:80/android/test.php", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(getApplicationContext(), "this is response: " + response,
Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "this is response: " + error,
Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("username", "hicham");
params.put("password", "hello");
return params;
}
};
Volley.newRequestQueue(this).add(request);
}
}
Please add the usesCleartextTraffic="true" tag in your AndroidManifest.xml accordingly to fix this issue.
<application
android:usesCleartextTraffic="true"
</application>
This issue occurs because you are trying to access an http url instead of https and there are new restrictions regarding this lately. Hence, only after adding the tag I mentioned, your HTTP requests will work.
Happy coding! :)
Well, I get Validation:com.android.volley.ParseError: org.json.JSONException:value false of type java.jang.Boolean cannot be converted to JSONObject error whenever I try to receive a boolean value, that is sent by a REST web service, in my android app using volley's JSONObjectRequest format.
I know that using StringRequest will be the easy way to solve this but I really wonder if there's another way to solve this.
My guess is that the primitive boolean value is the problem because it is not equevalent to a json object. so the exeption is thrown in the onResponse(JSONObject response) volley method.
here's the java REST web service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Boolean validate(CreditCard card) {
//instructions
if(/* some conditions */) {
cardList.put(card.getId(), card);
return true;
}
return false;
}
and the android app code:
public class MainActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_id = findViewById(R.id.id);
et_num = findViewById(R.id.number);
et_type = findViewById(R.id.type);
et_ctrlnb = findViewById(R.id.ctrlnum);
et_expd = findViewById(R.id.expdate);
b_validate = findViewById(R.id.validate);
b_validate.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == b_validate) {
String request_url = "http://192.168.191.1:8080/RESTCardValidator/rest/cardvalidator";
JSONObject cardDetails = new JSONObject();
try {
cardDetails.put("controlNumber", Integer.parseInt(et_ctrlnb.getText().toString()));
cardDetails.put("expiryDate", et_expd.getText().toString());
cardDetails.put("id", Long.parseLong(et_id.getText().toString()));
cardDetails.put("number", et_num.getText().toString());
cardDetails.put("type", et_type.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, request_url, cardDetails,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Toast.makeText(MainActivity.this, "Validation:" + response.toString(), Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Validation:" + error.toString(), Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(this).add(request);
}
}
as you see in the image the value true/false is received
First Screenshot-
Second Screenshot -
i have the following method inside mainActivity but i am trying to move it to separate class file so i can call it in other activities
public void addUser(){
StringRequest stringRequest = new StringRequest(Request.Method.POST,
constants.register_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(getApplicationContext(), response ,Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage() ,Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("username", "value");
params.put("email", "value");
params.put("password", "value");
return params;
}
};
requestHandler.getInstance(this).addToRequestQueue(stringRequest);
}
i have created a class called 'aqlCalls' and tried to put this and other methods inside but i can't figure how to do that..
any help appreciated..
I think you need to try to find the exact problem firstly.
According to the code in your method, I guess the problem is the Toast. If you want to use the Toast outside the Activity, you need to pass the context to this method. If you search for "android toast outside activity", you will get a lot of similar questions. such as this.
I suggest that adding a new parameter to context the addUser() and use the context to show the Toast.
And when using this method, pass a context (such as getApplicationContext()) to the method.
for example
void addUser(Context mcontext){
//all the toast usage change to
Toast.makeText(mContext, ....)
}
You can create your own listener to communicate with the activities and set the method static and save inside a class, passing the Context and use it in the request call.
public static void addUser(Context context, AddUserListener listener){
...
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listener.onSucces(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.onError(error.getMessage())
}
})
The Listener should be:
public interface AddUserListener{
void onSuccess(String response);
void onError(String message)
}
And finally in the activity do this:
MyClass.addUser(getApplicationContext(), new AddUserListener {
#Override
void onSuccess(String response){
... //Toast.makeText(...)
}
#Override
void onError(String message){
...//Toast.makeText(...)
}
});
Notice:
Please if you receive any Exception write down in your post, maybe you will receive an exception related with MainThread
I think your looking like something like this:
public class aqlCalls {
public static void addUser(Context context) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, constants.register_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("username", "value");
params.put("email", "value");
params.put("password", "value");
return params;
}
};
requestHandler.getInstance(context).addToRequestQueue(stringRequest);
}
}
Then you can call it from your class with:
public class OtherClass{
static void yourMethode() {
aqlCalls.addUser();
}
}
I think this is what you are looking for.
I am writing a login function for my application and I suddenly started getting this error: org.json.JSONException: Value Connection of type java.lang.String cannot be converted to JSONObject I don't recall modifying the code here at all and it used to work before. It suddenly stopped working when I started using the debug mode on android studio.
Here is a snippet of my code, the error seems to be on the 2 lines marked with /*ERROR*/:
private String loginUrl = "http://10.0.2.2/user/login.php";
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
request = new StringRequest(Request.Method.POST, loginUrl, new Response.Listener<String>() /*ERROR*/ {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response); /*ERROR*/
if (jsonObject.names().get(0).equals("success")) {
Toast.makeText(getApplicationContext(), jsonObject.getString("success"), Toast.LENGTH_SHORT).show();
email.setText("");
password.setText("");
Log.d("test", "Going to Main.class");
startActivity(new Intent(MainActivity.this, Main.class));
//setContentView(R.layout.activity_main);
} else {
Toast.makeText(getApplicationContext(), jsonObject.getString("error"), Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("email", email.getText().toString());
parameters.put("password", password.getText().toString());
return parameters;
}
};
requestQueue.add(request);
}
});
It seems like that the response object is not properly formatted to be converted into JSON object. Example.
org.json.JSONObject(String json) Creates a new JSONObject with name/value mappings from the JSON string.
This exception means that your response parameter does not contain a valid JSON
I am creating a button which when clicked calls the checkUserName method which searches the database and tells whether the username is available or not. The URL_CHECK_USERNAME responds "Username Available" or "Username not available".
public void checkUserName(View v){
String username = inputUserName.getText().toString().trim();
new CheckUsername().execute(username);
}
class CheckUsername extends AsyncTask<String, String, String>{
String r = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(RegisterActivity.this);
pDialog.setMessage("Checking Availability of this Username...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... params) {
//String r = null;
final String username = params[0];
StringRequest strReq = new StringRequest(Method.POST,
AppConfig.URL_CHECK_USERNAME, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
r = response;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.e(TAG, "Error in checking username." + volleyError.getMessage());
Toast.makeText(getApplicationContext(), volleyError.getMessage(), Toast.LENGTH_SHORT).show();
hideDialog();
}
}){
#Override
protected Map<String, String> getParams() {
Map<String, String> param = new HashMap<>();
//param.put("username", params[0]);
param.put("username", username);
return param;
}
};
AppController.getInstance().addToRequestQueue(strReq);
return r;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pDialog.dismiss();
Toast.makeText(RegisterActivity.this, s, Toast.LENGTH_SHORT).show();
}
}
This program displays an empty Toast everytime. What can be the problem?
From the code you posted I suppose you are using Volley as your network library.
If that's the case you should be aware that there's no need for that Asynctask of yours because Volley takes care of the threading for you.
The request will be executed in the background and the callback will be called asynchronously. That 's why your toasts are empty.
Create your StringRequest in your checkUsername(View) method and have the toast shown in the onResponse callback.