How to add Body request in url in Kotlin? - json

Here is my Code that for Volley Request:-
val searchRequest = object : JsonArrayRequest(Request.Method.GET,url,
Response.Listener { response ->
val result = response.toString()
},
Response.ErrorListener { error ->
Toast.makeText(activity, "Error!",Toast.LENGTH_LONG)
.show()
Log.d("ERROR",error.toString())
})
{
override fun getBody(): ByteArray {
// TODO add Body, Header section works //////////
return super.getBody()
}
override fun getBodyContentType(): String {
return "application/json"
}
override fun getHeaders() : Map<String,String> {
val params: MutableMap<String, String> = HashMap()
params["Search-String"] = songName
params["Authorization"] = "Bearer ${accessTx.text}"
return params
}
}
AppController.instance!!.addToRequestQueue(searchRequest)
I want to add this information in the body section
video_id = "BDJIAH" , audio_quality = "256"
here is the sample to add above information in the below segment.
{ "video_id":"ABCDE", "audio_quality":"256" }
Basically, I am facing problem in ByteArray section. That doesn't work for me.

You can use toByteArray() method of String class in Kotlin.
For example:
val charset = Charsets.UTF_8
val byteArray = "SomeValue".toByteArray(charset)
Also try to pass multiple values in the request body in this way:
val requestBody = "video_id = "+"ABCDE"+ "& audio_quality ="+ "256"
val charset = Charsets.UTF_8
val byteArray = requestBody.toByteArray(charset)

Related

I tried to parse a JSON file on my app but even if there is no error, my app doesn't run on the emulator

The problem might be that the app can't reach the json file I tried to parse it to.No error pops up in the run or build but it stops at"11/23 23:14:38: Launching 'app' on Device 4.Install successfully finished in 325 ms."Below is my code:
MainActivity
class MainActivity : AppCompatActivity() {
#SuppressLint("SuspiciousIndentation", "NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val usersList: ArrayList<UserModelClass> = ArrayList()
try {
val obj = JSONObject(getJSONFromAssets()!!)
val usersArray = obj.getJSONArray("owner")
for (i in 0 until usersArray.length()) {
val user = usersArray.getJSONObject(i)
val login = user.getInt("id")
val name = user.getString("name")
val url = user.getString("url")
val followers_url = user.getString("followers")
val starred_url = user.getString("stars")
val userDetails =
UserModelClass(login, name, url, followers_url , starred_url)
// add the details in the list
usersList.add(userDetails)
}
} catch (e: JSONException) {
//exception
e.printStackTrace()
}
val recyclerView = findViewById<RecyclerView>(R.id.rvUsersList)
val adapter = UserAdapter(this, usersList)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
}
private fun getJSONFromAssets(): String? {
var json: String? = null
val charset: Charset = Charsets.UTF_8
try {
val myUsersJSONFile = assets.open("JSON.json")
val size = myUsersJSONFile.available()
val buffer = ByteArray(size)
myUsersJSONFile.read(buffer)
myUsersJSONFile.close()
json = String(buffer, charset)
} catch (ex: IOException) {
ex.printStackTrace()
return null
}
return json
}
}
UserAdapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
class UserAdapter( val context: Context, val items: ArrayList<UserModelClass>) :
RecyclerView.Adapter<UserViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
return UserViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_user,
parent,
false
)
)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int {
return items.size
}
}
UserViewHolder
class UserViewHolder(view: View) : RecyclerView.ViewHolder(view) {
// Holds the TextView that will add each item to
var tvId : TextView
var tvName : TextView
var tvURL : TextView
var tvFollowers : TextView
var tvStars : TextView
init {
tvId = view.findViewById(R.id.tvId)
tvName = view.findViewById(R.id.tvName)
tvURL = view.findViewById(R.id.tvURL)
tvFollowers = view.findViewById(R.id.tvFollowers)
tvStars = view.findViewById(R.id.tvStars)
}
fun bind(item: UserModelClass) {
tvId.text = item.login.toString()
tvName.text = item.node_id
tvURL.text = item.avatar_url
tvFollowers.text = item.followers_url.toString()
tvStars.text = item.starred_url.toString()
}
}
UserModelClass
class UserModelClass(
val login: Int,
val node_id: String,
val avatar_url: String,
val followers_url: String,
val starred_url: String
)
Json.json
I don't need all the information from the json, I selected some of them
{
"total_count": 357602,
"incomplete_results": false,
"items": [
{
"id": 23096959,
"node_id": "...",
"name": "...",
"full_name": "...",
"private": false,
"owner": {
"login": "...",
"id": 4314092,
"node_id": "...",
"avatar_url": "https://...",
"url": "https://api.github.com/users/golang",
"followers_url": "https://api.github.com/users/golang/followers",
"following_url": "https://api.github.com/users/golang/following{/other_user}",
"starred_url": "https://api.github.com/users/golang/starred{/owner}{/repo}",
},
Actually it seems you are parsing it wrong. In your json, items is the array and owner is an object inside items array item.
You cannot access owner directly. Also you should give exact keys.
Like "followers_url" not just "followers"
Try the below code.
try {
val obj = JSONObject(getJSONFromAssets()!!)
val itemsArray = obj.getJSONArray("items")
for (i in 0 until itemsArray.length()) {
val user = itemsArray.getJSONObject(i)
val name = user.getString("name") // Getting name from item object
val owner = user.getJSONObject("owner") //Getting owner object from item object
//And below you need to get items from owner object not the user object.
val login = owner.getInt("id")
val url = owner.getString("url")
val followers_url = owner.getString("followers_url")
val starred_url = owner.getString("starred_url")
val userDetails =
UserModelClass(login, name, url, followers_url , starred_url)
// add the details in the list
usersList.add(userDetails)
}
} catch (e: JSONException) {
//exception
e.printStackTrace()
}

Nested JSON Objects in Kotlin with Volley

I am very new to this as you can probably tell, but i'm trying to parse a JSON url with Volley using Kotlin in Android Studio. The url contains nested Objects, not nested Arrays.
I can display everything inside "questionnaire", but I only want to display "typeOfQuestion". How do i do that?
MainActivity.kt:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
questionTV = findViewById(R.id.idTVQuestion)
answerTV = findViewById(R.id.idTVAnswer)
typeTV = findViewById(R.id.idTVType)
val queue: RequestQueue = Volley.newRequestQueue(applicationContext)
val request = JsonObjectRequest(Request.Method.GET, url, null, { response ->
loadingPB.setVisibility(View.GONE)
try {
val question: String = response.getString("question")
val answer: String = response.getString("answer")
val typeOfQuestion: String = response.getString("typeOfQuestion")
questionTV.text = question
answerTV.text = answer
typeTV.text = typeOfQuestion
} catch (e: Exception) {
e.printStackTrace()
}
}, { error ->
Log.e("TAG", "RESPONSE IS $error")
Toast.makeText(this#MainActivity, "Fail to get response", Toast.LENGTH_SHORT)
.show()
})
queue.add(request)
}
}
Heres the JSON:
{
"questionnaire": {
"question": "Where do you live?",
"answer": "In the mountains",
"typeOfQuestion": "Informative
}
}
You have object inside another json object.If you need to access field from child object you need to get child jsonObject and then get fields from object.
var questionnaire = response.getJSONObject("questionnaire")
You need to get fields from questionnaire object.Like.
val question: String = questionnaire.getString("question")
val answer: String = questionnaire.getString("answer")
val typeOfQuestion: String = questionnaire.getString("typeOfQuestion")

Post Request in Kotlin

I'm trying to do a post request in Android Studio written in Kotlin
I'm posting a JSON object to our server and then the server is returning a JSON object back. But what I'm doing here is decoding the response body as a string and then converting it into the data structure we need. I'm sure there is a better and simpler way to do what I need done.
My current code works but the major issue I'm having is formatting the string if our objects have nested objects which is why I want to figure out a better way to turn the response body into a json object.
I'm not too familiar with many request libraries for kotlin but I have looked into okhttp3 but I'm not sure how to post a json object, attach headers and decode the response body into a json object.
I know for okhttp3 I need to convert the json object to a string to post other than that I'm lost.
Breakdown of what's needed:
Post JSON Object To Server
Send Headers With Post Request
Decode Response Body into JSON Object/ Kotlin Equivalent
Simplify What I'm Trying to Do if Possible
This is the current code I have
private fun postRequestToGetDashboardData() {
val r = JSONObject()
r.put("uid", muid)
r.put("token", mtoken)
SendJsonDataToServer().execute(r.toString());
}
inner class SendJsonDataToServer :
AsyncTask<String?, String?, String?>() {
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
if (result.equals(null)) {
val t = Toast.makeText(this#Home, "No devices to display", Toast.LENGTH_LONG)
t.setGravity(Gravity.CENTER, 0, 0)
t.show()
} else {
intentForUnique.putExtra("FirstEndpointData", result)
var list = handleJson(result)
adapter.submitList(list)
dashboardItem_list.adapter = adapter
adapter.notifyDataSetChanged();
dashboardItem_list.smoothScrollToPosition(0);
}
}
override fun doInBackground(vararg params: String?): String? {
val JsonDATA = params[0]!!
var urlConnection: HttpURLConnection? = null
var reader: BufferedReader? = null
try {
val url = URL("URL");
urlConnection = url.openConnection() as HttpURLConnection;
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", mtoken);
urlConnection.setRequestProperty("Accept", "application/json");
val writer: Writer =
BufferedWriter(OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8"));
writer.write(JsonDATA);
writer.close();
val inputStream: InputStream = urlConnection.getInputStream();
if (inputStream == null) {
return null;
}
reader = BufferedReader(InputStreamReader(inputStream))
var inputLine: String? = reader.readLine()
if (inputLine.equals("null")) {
return null
} else {
return inputLine
}
} catch (ex: Exception) {
Log.e(TAG, "Connection Failed", ex);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (ex: Exception) {
Log.e(TAG, "Error closing stream", ex);
}
}
}
return null
}
}
private fun handleJson(jsonString: String?): ArrayList<SensorData> {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<SensorData>()
var x = 0
while (x < jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(x)
list.add(
SensorData(
jsonObject.getInt("deviceId"),
// jsonObject.getString("deviceName"),
jsonObject.getInt("battery"),
jsonObject.getString("dateTime"),
jsonObject.getInt("airValue"),
jsonObject.getInt("waterValue"),
jsonObject.getInt("soilMoistureValue"),
jsonObject.getInt("soilMoisturePercent")
)
)
x++
}
return list
}
So the json data being returned back is an array of this structure (our backend is written in Go)
type Device struct {
DeviceID int `bson:"deviceId" json:"deviceId"`
Battery int `bson:"battery" json:"battery"`
DateTime time.Time `bson:"dateTime" json:"dateTime"`
AirValue int `bson:"airValue" json:"airValue"`
WaterValue int `bson:"waterValue" json:"waterValue"`
SoilMoistureValue int `bson:"soilMoistureValue" json:"soilMoistureValue"`
SoilMoisturePercent int `bson:"soilMoisturePercent" json:"soilMoisturePercent"`
}

Iterating through JSON data

I am generating a JSON output in php which i need to use to fill line chart in android application writen in kotlin.
The JSON data is:
[{"reading_temperature":"14","hour":"01"},{"reading_temperature":"14","hour":"02"},{"reading_temperature":"14","hour":"03"},{"reading_temperature":"14","hour":"04"},{"reading_temperature":"14","hour":"05"},{"reading_temperature":"14","hour":"06"},{"reading_temperature":"14","hour":"07"},{"reading_temperature":"14","hour":"08"},{"reading_temperature":"14","hour":"09"},{"reading_temperature":"14","hour":"10"},{"reading_temperature":"14","hour":"11"},{"reading_temperature":"14","hour":"12"},{"reading_temperature":"14","hour":"13"},{"reading_temperature":"14","hour":"14"},{"reading_temperature":"14","hour":"15"},{"reading_temperature":"14","hour":"16"},{"reading_temperature":"14","hour":"17"},{"reading_temperature":"14","hour":"18"},{"reading_temperature":"14","hour":"19"},{"reading_temperature":"14","hour":"20"},{"reading_temperature":"14","hour":"21"},{"reading_temperature":"14","hour":"22"},{"reading_temperature":"14","hour":"23"}]
This is the part of the code where i get the JSON:
override fun doInBackground(vararg params: String?): String? {
var response:String?
try{
response = URL("https://127.0.0.1/weatherStation/temperatureDaily.php").readText(
Charsets.UTF_8
)
}catch (e: Exception){
response = null
}
return response
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
try {
val jsonObj = JSONObject(result)
} catch (e: Exception) {
}
}
Now i need to use that data to populate the line chart, this is hardcoded data which i need to exchange with JSON
private fun setupLineChartDataTemperatura() {
val yVals = ArrayList<Entry>()
//This next part i need to dynamically generate from JSON,
//first float value and last string value should be `"hour":"xx"`
// and second float value should be `[{"reading_temperature":"xx"`
yVals.add(Entry(0f, 4f, "0"))
yVals.add(Entry(1f, 5f, "1"))
yVals.add(Entry(1.5f, 4f, "1.5"))
yVals.add(Entry(2f, 5f, "2"))
yVals.add(Entry(3f, 3f, "3"))
yVals.add(Entry(4f, 2f, "4"))
val set1: LineDataSet
set1 = LineDataSet(yVals, "Temperatura")
val dataSets = ArrayList<ILineDataSet>()
dataSets.add(set1)
val data = LineData(dataSets)
chart1.setData(data)
chart1.description.isEnabled = false
chart1.legend.isEnabled = true
chart1.setPinchZoom(false)
chart1.xAxis.enableGridDashedLine(5f, 5f, 0f)
chart1.axisRight.enableGridDashedLine(5f, 5f, 0f)
chart1.axisLeft.enableGridDashedLine(5f, 5f, 0f)
chart1.setDrawGridBackground(true)
chart1.xAxis.labelCount = 11
chart1.xAxis.position = XAxis.XAxisPosition.BOTTOM
chart1.setTouchEnabled(true)
chart1.invalidate()
}
I have managed to do it:
val jsonTemperatureData = JSONArray(result)
for (i in 0 until jsonTemperatureData.length()) {
val item = jsonTemperatureData.getJSONObject(i)
val reading_temperature = item.getString("reading_temperature")
val hour = item.getString("hour")
yVals.add(Entry(hour.toFloat(), reading_temperature.toFloat(), hour.toString()))
}

How to add Body in Url in Volley request in Kotlin?

Here is my Code that for Volley Request:-
val searchRequest = object : JsonArrayRequest(Request.Method.GET,url,
Response.Listener { response ->
val result = response.toString()
},
Response.ErrorListener { error ->
Toast.makeText(activity, "Error!",Toast.LENGTH_LONG)
.show()
Log.d("ERROR",error.toString())
})
{
override fun getBody(): ByteArray {
// TODO add Body, Header section works //////////
return super.getBody()
}
override fun getBodyContentType(): String {
return "application/json"
}
override fun getHeaders() : Map<String,String> {
val params: MutableMap<String, String> = HashMap()
params["Search-String"] = songName
params["Authorization"] = "Bearer ${accessTx.text}"
return params
}
}
AppController.instance!!.addToRequestQueue(searchRequest)
I want to add this information in the body section
video_id = "BDJIAH" ,
audio_quality = "256"
here is the sample to add above information in the below segment.
{
"video_id":"ABCDE",
"audio_quality":"256"
}
Basically, I am facing problem in ByteArray section. That doesn't work for me.
This function i created to send a call to server and this is how you will add body in your call.
fun sendcall() {
//RequestQueue initialized
mRequestQueue = Volley.newRequestQueue(this)
//String Request initialized
mStringRequest = object : StringRequest(Request.Method.POST, url, Response.Listener { response ->
Toast.makeText(applicationContext, "Logged In Successfully", Toast.LENGTH_SHORT).show()
}, Response.ErrorListener { error ->
Log.i("This is the error", "Error :" + error.toString())
Toast.makeText(applicationContext, "Please make sure you enter correct password and username", Toast.LENGTH_SHORT).show()
}) {
override fun getBodyContentType(): String {
return "application/json"
}
#Throws(AuthFailureError::class)
override fun getBody(): ByteArray {
val params2 = HashMap<String, String>()
params2.put("Login","your credentials" )
params2.put("Password", "your credentials")
return JSONObject(params2).toString().toByteArray()
}
}
mRequestQueue!!.add(mStringRequest!!)
}
Volley post request in kotlin with params
private fun loginUser() {
val username: String = etName.getText().toString().trim()
val password: String = etPass.getText().toString().trim()
val stringRequest: StringRequest = object : StringRequest( Method.POST, LOGINURL,
Response.Listener { response ->
Toast.makeText(this, response, Toast.LENGTH_LONG).show()
try {
val jsonObject = JSONObject(response)
//Parse your api responce here
/*val intent = Intent(this, MainActivity::class.java)
startActivity(intent)*/
} catch (e: JSONException) {
e.printStackTrace()
}
},
Response.ErrorListener { error ->
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
}) {
override fun getParams(): Map<String, String> {
val params: MutableMap<String, String> = HashMap()
//Change with your post params
params["username"] = username
params["password"] = password
return params
}
}
val requestQueue = Volley.newRequestQueue(this)
requestQueue.add(stringRequest)
}