I can send JSON object request to post data on the server using volley but can't work properly. It always shows a volley failure error. I tried it many times but. I can't know why it happens Kindly share with me the preferable answer Kindly.
private fun login() {
val params = JSONObject()
params.put("email",login_email.text.toString())
params.put("password",login_password.text.toString())
val url = "http://192.168.10.100/fitness_app/api/v1/login"
val queue = Volley.newRequestQueue(this)
val request = object : JsonObjectRequest(
Request.Method.POST,url,params,
Response.Listener<JSONObject> { response ->
val code = response.getInt("code")
if(code==101)
{
Toast.makeText(this,"Successfully login", Toast.LENGTH_SHORT).show()
}
else if(code==102)
{
Toast.makeText(this,"Unauthorized user", Toast.LENGTH_SHORT).show()
}
else if(code==103)
{
Toast.makeText(this,"Email does not exist", Toast.LENGTH_SHORT).show()
}
}, Response.ErrorListener {
Toast.makeText(this,"Something went wrong. Please try later.Volley Error", Toast.LENGTH_SHORT).show()
}
)
{
}
queue.add(request)
}
The code given above is exactly write . I just forget to make httptrafficlibrary true in manifest that is false by default.
Related
I'm trying to take data from a mySQL database and my code take it correctly.
The problem is that I have the information in a JsonObjectRequest and out of it, I can't use it. My idea was to use variables to save some of the information I need.
Something like this:
val queue=Volley.newRequestQueue(this)
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET,url,null,
{ response ->
emailGet = response.getString("email")
usernameGet = response.getString("name")
}, { error ->
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}
)
queue.add(jsonObjectRequest)
As I said the problem here is that emailGet and usernameGet (variables declared before this code bloc) store the values only inside the JsonObjectRequest, out of it the variables are empty.
Example:
val queue=Volley.newRequestQueue(this)
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET,url,null,
{ response ->
emailGet = response.getString("email")
usernameGet = response.getString("name")
Toast.makeText(this, emailGet, Toast.LENGTH_LONG).show()
}, { error ->
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}
)
queue.add(jsonObjectRequest)
Toast.makeText(this, usernameGet, Toast.LENGTH_LONG).show()
Here the Toast will print on the screen only the emailGet content because it's inside the JsonObjectRequest, the Toast that have to print the usernameGet value will not do it.
Looking for information I have found that this problem could be because this function is asynchronous and I found a possible solution in Java that I tried to translate to Kotlin.
val queue=Volley.newRequestQueue(this)
val future : RequestFuture<JSONObject> = RequestFuture.newFuture()
val request = JsonObjectRequest(
Request.Method.GET, url, null, future, future)
queue.add(request)
try{
var response = future.get()
} catch (e : InterruptedException){
} catch (e : ExecutionException){
}
I do not really understand this second code, but it still doesn't working, the response variable is always empty and the program stays in an infinite loop inside that try.
If you want to use the emailGet and usernameGet variables, you should do it within the callback:
val queue = Volley.newRequestQueue(this)
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET, url, null,
{ response ->
emailGet = response.getString("email")
usernameGet = response.getString("name")
// TODO do something with the variables here
}, { error ->
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}
)
queue.add(jsonObjectRequest)
If instead, you have a method method doSomething() that runs immediately after the response is received:
fun doSomething(email:String, username:String){
// TODO do something with the variables here
}
You can replace the TODO comment in the first code snippet with doSomething(emailGet, usernameGet).
The 4th and 5th parameters for JsonObjectRequest are in fact objects of types Response.Listener and Response.ErrorListener. These two listeners are Single Abstract Method interfaces. If expanded it would look like this:
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET, url, null,
object : Response.Listener {
override fun onResponse(response: JSONObject) {
emailGet = response.getString("email")
usernameGet = response.getString("name")
doSomething(emailGet, usernameGet)
}
},
object : Response.ErrorListener {
override fun onErrorResponse(error: VolleyError) {
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}
}
)
The lambda syntax you were using was a short hand of SAM interfaces.
The simplest way is using #ttyip's answer but you could also use live data and observing it! You're calling an asynchronous method and there's going to be some delay(network API calling and this delay depends on user's internet connection etc) So First you'll need to add jetPack's lifeCycle components inside your project:
dependencies {
def lifecycle_version = "2.4.0-alpha02"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// Annotation processor
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
}
After syncing your project, define global inside your activity/fragment:
val email: MutableLiveData<String> = MutableLiveData<String>()
val username: MutableLiveData<String> = MutableLiveData<String>()
And inside your response:
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET,url,null,
{ response ->
val emailGet = response.getString("email")
val usernameGet = response.getString("name")
email.postValue(emailGet)
username.postValue(usernameGet)
}, { error ->
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}
)
And somewhere inside your activity just observe your livedata:
email.observe(this, Observer { string ->
// Do some work
})
username.observe(this, Observer { string ->
// Do some work
})
Im trying to get the json data from below URL
https://newsapi.org/v2/everything?q=tesla&from=2021-05-07&sortBy=publishedAt&apiKey=c9e4ed47388d413c8af23fc46a330f8e
But when I run the app it shows
31029-31125 E/Volley: [228776] NetworkUtility.shouldRetryException: Unexpected response code 403 for https://newsapi.org/v2/everything?q=tesla&from=2021-02-23&sortBy=publishedAt&apiK 20ey=c9e4ed47388d413c8af23fc46a330f8e
31029-31125 E/Volley: [228776] NetworkUtility.shouldRetryException: Unexpected response code 403 for https://newsapi.org/v2/everything?q=tesla&from=2021-02-23&sortBy=publishedAt&apiK 20ey=c9e4ed47388d413c8af23fc46a330f8e
But when I enter the URL in chrome browser it shows the json data normally but I got getting the same thing in my app
here is my code in kotlin
fun getNews(context: Context){
var queue: RequestQueue = Volley.newRequestQueue(context)
val url = "https://newsapi.org/v2/everything?q=tesla&from=2021-05-07&sortBy=publishedAt&apiKey=c9e4ed47388d413c8af23fc46a330f8e"
val request = JsonObjectRequest(
Request.Method.GET, url, null,
{ response ->
var list: MutableList<newModel> = mutableListOf<newModel>()
try {
var rootArray: JSONArray = response.getJSONArray("articles")
for(i in 0 until response.length()){
var dataObject: JSONObject = rootArray.get(i) as JSONObject
list.add(newModel(dataObject.getString("urlToImage") , dataObject.getString("title") , dataObject.getString("description") , dataObject.getString("url")))
}
} catch (e: Exception) {
Toast.makeText(
context,
"error while parsing the jsonObject/array",
Toast.LENGTH_LONG
).show()
}
callBack.gotTheNewsData(list)
}) { error ->
Toast.makeText(context, "Error in responce", Toast.LENGTH_SHORT).show()
}
queue.add(request)
}
I was facing the same error and I solved it by passing a header "Mozilla/5.0" to the request.
This can be done in this way on your code.
fun getNews(context: Context){
var queue: RequestQueue = Volley.newRequestQueue(context)
val url = "Your URL here"
val request = object: JsonObjectRequest(
Request.Method.GET, url, null,
{ response ->
var list: MutableList<newModel> = mutableListOf<newModel>()
try {
var rootArray: JSONArray = response.getJSONArray("articles")
for(i in 0 until response.length()){
var dataObject: JSONObject = rootArray.get(i) as JSONObject
list.add(newModel(dataObject.getString("urlToImage") , dataObject.getString("title") , dataObject.getString("description") , dataObject.getString("url")))
}
} catch (e: Exception) {
Toast.makeText(
context,
"error while parsing the jsonObject/array",
Toast.LENGTH_LONG
).show()
}
callBack.gotTheNewsData(list)
}) { error ->
Toast.makeText(context, "Error in responce", Toast.LENGTH_SHORT).show()
}
// overriding function to add Headers.
{
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["User-Agent"]="Mozilla/5.0"
return headers
}
}
queue.add(request)
}
It is important to use the object keyword before the construction of the request in order to be able to override the getHeaders() method.
This answer helped me in adding a custom header in Volley request with kotlin.
Override header ["User-Agent"]="Mozilla/5.0"
Or You can use this NewsApi which dont require apikey
https://github.com/SauravKanchan/NewsAPI
I'm creating a login for my application.
I am currently stuck in posting problems to my API
This is my API that which is made to support login.
{
success: false,
message: "Please provide complete and accurate information.",
data: [ ]
}
fun loginUrlSuccess(urlApi : String) {
Log.d("login", urlApi)
authSignin_cgi = gson.fromJson(urlApi, DtoProfile::class.java)
loginsSuccess = authSignin_cgi.success
val queue = Volley.newRequestQueue(context)
val stringReq = object : StringRequest(Request.Method.POST,urlApi,Response.Listener<String>{ response ->
Log.w("response",response)
Toast.makeText(context,"Loging success..",Toast.LENGTH_SHORT).show()
if (loginsSuccess){
Toast.makeText(context,authSignin_cgi.message,Toast.LENGTH_LONG).show()
} else {
Toast.makeText(context,authSignin_cgi.message,Toast.LENGTH_LONG).show()
}
},Response.ErrorListener { error ->
Log.w("error", error.toString())
Toast.makeText(context, "error..$error",Toast.LENGTH_SHORT).show()
}){
override fun getParams(): MutableMap<String, String> {
val param = HashMap<String, String>()
val userEmail = textEmail.text.toString().trim()
val userPassword = textPassword.text.toString().trim()
param["useremail"] = userEmail
param["userpassword"] = userPassword
return param
}
}
queue.add(stringReq)
}
I get an error from the Logcat screen.
So what do I have to do?
04-04 15:31:43.614 8365-8699/com.example.atimeonlin5 E/Volley: [700] NetworkDispatcher.processRequest: Unhandled exception java.lang.RuntimeException: Bad URL {"success":false,"message":"โปรดระบุข้อมูลให้ถูกต้องครบถ้วน","data":[]}
java.lang.RuntimeException: Bad URL {"success":false,"message":"โปรดระบุข้อมูลให้ถูกต้องครบถ้วน","data":[]}
All right , you should try to construct an Url object instead of type String !
You should use an url (like "http://www.google.com"), not a random string. Your urlApi is not url.
Example from doc:
val textView = findViewById<TextView>(R.id.text)
// ...
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(this)
val url = "http://www.google.com"
// Request a string response from the provided URL.
val stringRequest = StringRequest(Request.Method.GET, url,
Response.Listener<String> { response ->
// Display the first 500 characters of the response string.
textView.text = "Response is: ${response.substring(0, 500)}"
},
Response.ErrorListener { textView.text = "That didn't work!" })
// Add the request to the RequestQueue.
queue.add(stringRequest)
I'm creating the login page for my application and it gives me the error of Cannot infer a type of this parameter. Please specify it explicitly.
It gives error only within error and response. Any clue why it is like that?
var rq: RequestQueue = Volley.newRequestQueue(this)
var sr = StringRequest(Request.Method.GET, url, Response.Listener { response ->
if(response.equals("0"))
Toast.makeText(this, "Login failed.", Toast.LENGTH_LONG).show()
else
var i = Intent(this,LoggedinActivity::class.java)
startActivity(i)
Toast.makeText(this, "User created successfully.", Toast.LENGTH_LONG).show()
}, Response.ErrorListener {
error ->
Toast.makeText(this, error.message, Toast.LENGTH_LONG).show()
})
rq.add(sr)
The problem has been arised because I didn't check all the brackets correctly, thus if statements didn't work correctly and it was giving error because of that.
Sorry for the inconvenience. I wish you great week ahead. I checked the first answer as correct one.
It might be your lack of brackets around your if and else.
Try this:
val rq: RequestQueue = Volley.newRequestQueue(this)
val sr = StringRequest(Request.Method.GET, url, Response.Listener { response ->
if(response == "0") {
Toast.makeText(this, "Login failed.", Toast.LENGTH_LONG).show()
}
else {
val i = Intent(this, MainActivity::class.java)
startActivity(i)
Toast.makeText(this, "User created successfully.", Toast.LENGTH_LONG).show()
}
}, Response.ErrorListener {
error ->
Toast.makeText(this, error.message, Toast.LENGTH_LONG).show()
})
rq.add(sr)
The this should refer to activity context otherwise the code believes that it is the Response.Listener additionally as mentioned by user8159708 you need the brackets, at least to the else statement.
val rq: RequestQueue = Volley.newRequestQueue(this)
val sr = StringRequest(Request.Method.GET, url, Response.Listener { response ->
if(response == "0") {
Toast.makeText(this#MainActivity, "Login failed.", Toast.LENGTH_LONG).show()
}
else {
val i = Intent(this#MainActivity, MainActivity::class.java)
startActivity(i)
Toast.makeText(this#MainActivity, "User created successfully.", Toast.LENGTH_LONG).show()
}
}, Response.ErrorListener {
error ->
Toast.makeText(this#MainActivity, error.message, Toast.LENGTH_LONG).show()
})
rq.add(sr)
Edit:
Proper syntax in kotlin is this#MainActivity according to this post
i am trying Android App to connect the Mysql through API call. I am following this article to create the app.
https://www.simplifiedcoding.net/volley-with-kotlin/
But I have populate the mysql JSON result into 2 textView android objects. I am getting error while compile the String Request.
type mismatch: Expected string, Found: int, and another error which are attached here.
StringRequest Function error
Type mismatch error
My code is here. I am new to this Kotlin, I couldn't figure out upto my level. where is the problem caused.. How do I resolve this?
//MainActivity.kt
val requestQueue = Volley.newRequestQueue(this#MainActivity)
downtxtvalue = findViewById<TextView>(R.id.downtxt) as TextView
uploadtxtvalue = findViewById<TextView>(R.id.uptxt) as TextView
//findViewById<Button>(R.id.btnGetspeed).setOnContextClickListener(getSpeed()){
val stringRequest = StringRequest(Request.Method.GET,URL_GET_ARTIST;
Response.Listener<String> { s ->
try {
val obj = JSONObject(s)
if (!obj.getBoolean("error")) {
val array = obj.getJSONArray("internet")
for (i in 0..array.length() - 1) {
val objValue = array.getJSONObject(i)
objValue.getInt("download_value")
objValue.getInt("upload_value")
}
}
} catch (e: JSONException) {
e.printStackTrace()
}
},
Response.ErrorListener { volleyError -> Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show() }
requestQueue.add(stringRequest)
} }