Empty ArrayList after using Volley in Kotlin - android

I'm working on a simple app where I add elements in a ListView dynamically, for this I'm using Volley to read JSON and then add all the information inside a data class, as I saw in other questions Volley is asynchronous so when I try to get the size of my list it return 0 because it was executed before Volley.
I can't figure out how to wait for volley to finish before continuing with the code in Kotlin, this is the code where I get the data:
private fun getUsers() {
val url = ""
val requestQueue = Volley.newRequestQueue(this)
val request = JsonObjectRequest(Request.Method.GET, url, null, {
response ->try {
val jsonArray = response.getJSONArray("" + "data")
for (i in 0 until jsonArray.length()) {
val distr = jsonArray.getJSONObject(i)
val getUser = distr.getString("Utilizador").toString()
val getCargo = distr.getString("Cargo").toString()
val getEstado = distr.getString("Estado").toString().toInt()
listUtilizadores.add(Utilizadores(getUser, getCargo, getEstado))
}
} catch (e: JSONException) {
e.printStackTrace()
}
}, { error -> error.printStackTrace() })
requestQueue.add(request)
}
And how I call it inside onCreate()
getUsers()
Log.i("Testing", "Value: " + listUtilizadores.size)
Thank you

Can you try with JsonArrayRequest.
val request =JsonArrayRequest(
url,
Response.Listener { response ->
if (response != null) {
for (i in 0 until response.length()) {
try {
val distr = response.getJSONObject(i)
val getUser = distr.getString("Utilizador").toString()
val getCargo = distr.getString("Cargo").toString()
val getEstado = distr.getString("Estado").toString().toInt()
listUtilizadores.add(Utilizadores(getUser, getCargo, getEstado))
}
} catch (e: JSONException) {
e.printStackTrace()
}
}, { error -> error.printStackTrace() })
requestQueue.add(request)
}

Related

Unable to Log certain lines

My onCreate() of MainActivity contains this part of code:
val weatherService = RetrofitFactory.retrofit(AppConstants.OWM_API_URL)
.create(OwmApi::class.java)
GlobalScope.launch(Dispatchers.Main) {
val request = weatherService.getCurrentWeatherDataByName("Bengaluru", "metric")
Log.i("Response 0", 0.toString())
try {
val response = request.await()
if(response.isSuccessful) {
Log.i("Response 2", 2.toString())
val weatherResponse = response.body()
Log.i("Response 3", 3.toString())
Log.i("Response", weatherResponse.toString())
println(weatherResponse)
}
else {
Log.i("Response 5", 5.toString())
Log.d(TAG, response.errorBody().toString())
}
}
catch (e: Exception) {
e.stackTrace
}
}
The weatherService's client contains an interceptor whose definition is as follows:
private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
Now when I run my app, I only see the Log with tag of Response 0, but not Response, or even the else part of my code when I change the query parameters to invalid values. Maybe this has something to do with the loggingInterceptor but I'm still not sure why certain Log messages don't appear despite the response.isSuccessful part being true.
You have to call your api call in background thread may be it's getting exception.
so try like below
val weatherService = RetrofitFactory.retrofit(AppConstants.OWM_API_URL)
.create(OwmApi::class.java)
GlobalScope.launch(Dispatchers.IO) {
val request = weatherService.getCurrentWeatherDataByName("Bengaluru", "metric")
Log.i("Response 0", 0.toString())
try {
val response = request.await()
if(response.isSuccessful) {
Log.i("Response 2", 2.toString())
val weatherResponse = response.body()
Log.i("Response 3", 3.toString())
Log.i("Response", weatherResponse.toString())
println(weatherResponse)
}
else {
Log.i("Response 5", 5.toString())
Log.d(TAG, response.errorBody().toString())
}
}
catch (e: Exception) {
e.stackTrace
}
}
Try to set "No filter" option on

Volley - JsonObjectRequest - parseNetworkResponse() is not being called

I would like to save response code from volley calls to db, but it seems like parseNetworkResponse() is not being called. Any idea why does it behave like this?
All of my calls are GET, some has code 500 and some has code 200 with json response, so I think it should be called.
private fun createCall(url: String, type: Int, data: JSONObject, callback: Int, request: DbRequestEntity) {
val jsonRequest = object : JsonObjectRequest(type, url, data,
Response.Listener { response ->
Log.d(tag, "Response $response")
try {
callback(response, data, callback, request)
} catch (e: Exception) {
request.responseCode = 999
request.responseMessage = e.message
db.requestMoodel().update(request)
Log.d(tag, "API callback error $e ${e.localizedMessage} ${e.stackTrace}")
}
},
Response.ErrorListener { error ->
Log.d(tag, "API error $error")
errorCallback(error, callback)
}
) {
val tag = "JsonObjectRequest"
override fun getHeaders(): Map<String, String> {
val headers = HashMap<String, String>()
headers[ConstantsStorage.API_HEADER_CLIENT_ID] = ConstantsStorage.API_HEADER_CLIENT_ID_VALUE
headers[ConstantsStorage.API_HEADER_CLIENT_CONTENT_TYPE] = ConstantsStorage.API_HEADER_CLIENT_CONTENT_TYPE_VALUE
return headers
}
override fun parseNetworkResponse(response: NetworkResponse): Response<JSONObject> {
Log.d(tag, "Response code = ${response.statusCode}") //not getting this message to Logcat
return super.parseNetworkResponse(response)
}
}
queue.add(jsonRequest)
}
Replace your parseNetworkResponse function with below code
override fun parseNetworkResponse(response: NetworkResponse): Response<JSONObject> {
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)
}

Return response of android volley in workmanager

I've been trying to implement android volley with Workmanager for background data upload. No issues at all with implementation, but it's really hard to catch and return response result via Result.success to register.
override fun doWork(): Result {
var volley = VolleySingleTon.getInstance(mContext)
.syncLocationData(mContext, location, success = Function { collection ->
ERROR HERE************
**Need to return the return Result.success()**
**but i can't return the above**
}, failure = Function { collection ->
ERROR HERE************
**Need to return the return Result.failure()**
**but i can't return the above**
})
}
Volley request method class
fun syncLocationData(
context: Context,
location: List<VehicleLocation>, success: Function<RestCollection, Any>, failure: Function<RestCollection, Any>
) {
var jsonObject: JSONObject? = null
val jsonString = RestUtil.getGson().toJson(location)
try {
jsonObject = JSONObject(jsonString)
} catch (e: JSONException) {
e.printStackTrace()
}
addToRequestQueue(
JsonObjectRequest(
Request.Method.POST,
AppConstants.WEB_SERVER.toString + AppConstants.SYNC_LOC_DATA.toString, jsonObject,
SuccessHandler(context, null, success),
ErrorHandler(context, null, failure)
)
)
}
The handler used to gather the result from response
class SuccessHandler(
val context: Context,
private val progressBar: ProgressBar?,
private val successCallBack: Function<RestCollection, Any>
) : Response.Listener<JSONObject> {
override fun onResponse(json: JSONObject?) {
if (json != null) {
progressBar?.visibility = View.GONE
val response: ApplicationResponse =
RestUtil.getGson().fromJson(json.toString(), ApplicationResponse::class.java)
successCallBack.apply(response.collection)
}
}
}
Is there any workaround for this? Thanks!!
You can use a RequestFuture which is a Volley object. It helps you create a synchronous call in the Worker class
#NonNull
#Override
public Result doWork() {
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, "https://jsonplaceholder.typicode.com/todos/1", null, future, future);
VolleySingleton.getmInstance(getApplicationContext()).addToRequestQueue(request);
try {
JSONObject response = future.get(60, TimeUnit.SECONDS); // this will block
Log.d(TAG, response.toString());
return Result.success();
} catch (InterruptedException e) {
e.printStackTrace();
// exception handling
return Result.failure();
} catch (ExecutionException e) {
e.printStackTrace();
return Result.failure();
// exception handling
} catch (TimeoutException e) {
e.printStackTrace();
return Result.failure();
}
}

how to Authenticate with Volley in android

i have a web service in this url : https://server_IP:9443/api/v1/ssids.json/
but it needs login in this page : https://server_IP:9443/login
when i make the request with the credentials in the headers , i got "Unexpected response code 401"
so how can i authenticate and get the json.
here is my code :
val request = object : StringRequest(Request.Method.GET, url, Response.Listener { response ->
if (response != null) {
Log.e("Your Array Response", response)
} else {
Log.e("Your Array Response", "Data Null")
}
}, Response.ErrorListener { error -> Log.e("error is ", "" + error) }) {
override fun getHeaders() : Map<String, String> {
val username ="admin"
val password = "admin"
val auth = "$username:$password"
var data = auth.toByteArray()
var base64 = Base64.encodeToString(data, Base64.NO_WRAP)
var headers = HashMap<String, String>()
headers.put("Authorization",base64)
headers.put("accept-language","EN")
headers.put("Content-type","application/json")
headers.put("Accept","application/json")
return headers
}
}
val queue = Volley.newRequestQueue(this)
queue.add(request)

Write in a database with Android

I am trying to write in a database with the library Volley using Kotlin and when I try nothing happened. I used Postman to see if there is a problem from the server and all is okay. According to me the problem comes from this part of my code:
val stringRequest = object : StringRequest(Request.Method.POST, "myURL",
Response.Listener<String> { response ->
try {
val obj = JSONObject(response)
Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()
} catch (e: JSONException) {
e.printStackTrace()
}
},
object : Response.ErrorListener {
override fun onErrorResponse(volleyError: VolleyError) {
Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show()
}
}) {
#Throws(AuthFailureError::class)
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("name", name)
params.put("genre", genre)
return params
}
}
VolleySingleton.instance?.addToRequestQueue(stringRequest)
Thank you a lot to try to solve my problem !!!

Categories

Resources