I'm building an android app just to show or convert some cripto to USD.. But I dont know how to use and API and get the exact price value of bitcoin(any cripto)...How do I filter the json to get just the right value?
private fun converter(){
val selectedCurrency = findViewById<RadioGroup>(R.id.radioGroup)
val editField = findViewById<EditText>(R.id.edit_field)
val value = editField.text.toString()
if (value.isEmpty() || value == ".")
return
Thread{
//Para here
val url = URL("https://api.coinmarketcap.com/data-api/v3/cryptocurrency/listing?start=1&limit=500")
val conn = url.openConnection() as HttpsURLConnection
try {
val data = conn.inputStream.bufferedReader().readText()
// {"price": 32000.000} what i want to get and idk how
val obj = JSONObject(data)
runOnUiThread{
val res = obj
result.text = res.toString()
result.visibility = View.VISIBLE
}
}finally{
conn.disconnect()
}
}.start()
Related
If I have this url address
https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117
How could I get (or split) parameters (avoiding hard coding)?
I need separated values:
https
googledroids.com
/post.html
parameters and values: {limit=25, time=0dfdbac117, since=1374196005, md5=d8959d12ab687ed5db978cb078f1e}
The following should work, it gives a list of parameter values rather than just one.
val uri = Uri.parse("https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117")
val host = uri.host // googledroids.com
val protocol = uri.scheme // https
val path = uri.path // /post.html
val parameters = uri.queryParameterNames.associateWith { uri.getQueryParameters(it) } // {limit:[25], time:[0dfdbac117], since:[1374196005], md5:[d8959d12ab687ed5db978cb078f1e]}
Using the class:
import android.net.Uri
We can the values protocol, server, path, parameters and we have the option to get a specific parameter value using uri.getQueryParameter():
val url = "https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117"
val uri = Uri.parse(url)
val protocol = uri.scheme // https
val server = uri.authority // googledroids.com
val path = uri.path // /post.html
val args = uri.queryParameterNames //size: 4 parameters
val limit = uri.getQueryParameter("limit") // limit: "25"
println("value of limit: $limit")
we can get a list of parameters too (Using this question´s answer (java)):
val url = "https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117"
val uri = Uri.parse(url)
val protocol = uri.scheme // https
val server = uri.authority // googledroids.com
val path = uri.path // /post.html
val args = uri.queryParameterNames //size: 4 parameters
val query = uri.query
val data: MutableMap<String, String> = HashMap()
for (param in query?.split("&")?.toTypedArray()!!) {
val params = param.split("=").toTypedArray()
val paramName = URLDecoder.decode(params[0], UTF_8)
var value = ""
if (params.size == 2) {
value = URLDecoder.decode(params[1], UTF_8)
}
data[paramName] = value
}
println("$data") //{limit=25, time=0dfdbac117, since=1374196005, md5=d8959d12ab687ed5db978cb078f1e}
this is a better and easy way to get the paramaters and values using uri.queryParameterNames:
val uri = Uri.parse(url)
val protocol = uri.scheme
val server = uri.authority
val path = uri.path
val args = uri.queryParameterNames
val limit = uri.getQueryParameter("limit")
val query = uri.query
for (paramName in uri.queryParameterNames) {
println("parameter => $paramName | value: ${uri.getQueryParameter(paramName)}")
}
}
I'm trying to parse this public Api JSON "https://api.quarantine.country/api/v1/summary/latest"
and the problem starts when I need to parse Object "Region" which is a Map of key String value Object Country. I'm doing this manually on purpose just for practice.
This is my code till now:
private fun writeData(json: String?) {
val jsonObj = JSONObject(json)
val data = jsonObj.getJSONObject("data")
val summary = data.getJSONObject("summary")
val total_casesSummary = summary.getInt("total_cases")
val active_casesSummary = summary.getInt("active_cases")
val deathsSummary = summary.getInt("deaths")
val recoveredSummary = summary.getInt("recovered")
val criticalSummary = summary.getInt("critical")
val testedSummary = summary.getInt("tested")
val death_ratioSummary = summary.getDouble("death_ratio")
val recovery_ratioSummary = summary.getDouble("recovery_ratio")
val summaryObj = ChangeSummary(total_casesSummary,
active_casesSummary,
deathsSummary,
recoveredSummary,
criticalSummary,
testedSummary,
death_ratioSummary,
recovery_ratioSummary)
val change = data.getJSONObject("change")
val total_casesChange = data.getInt("total_cases")
val active_casesChange = data.getInt("active_cases")
val deathsChange = data.getInt("deaths")
val recoveredChange = data.getInt("recovered")
val criticalChange = data.getInt("critical")
val testedChange = data.getInt("tested")
val death_ratioChange = data.getDouble("death_ratio")
val recovery_ratioChange = data.getDouble("recovery_ratio")
val changeObj = ChangeSummary(total_casesChange,
active_casesChange,
deathsChange,
recoveredChange,
criticalChange,
testedChange,
death_ratioChange,
recovery_ratioChange)
val regions = data.getJSONObject("regions")
}
and there problem starts here when I need to read countries from object regions:
"regions":{
"usa":{
"name":"USA",
"iso3166a2":"US",
"iso3166a3":"USA",
"iso3166numeric":"",
"total_cases":34219271,
"active_cases":5440268,
"deaths":612532,
"recovered":28166471,
"critical":5259,
"tested":487505878,
"death_ratio":0.017900205997959454,
"recovery_ratio":0.8231172136893273,
"change":{
"total_cases":10304,
"active_cases":-36393,
"deaths":179,
"recovered":46518,
"death_ratio":-1.5913145237633763e-7,
"recovery_ratio":0.0011118897635858938
}
},
"india":{
"name":"India",
"iso3166a2":"IN",
"iso3166a3":"IND",
"iso3166numeric":"",
"total_cases":28996949,
"active_cases":1308806,
"deaths":351344,
"recovered":27336799,
"critical":8944,
"tested":366334111,
"death_ratio":0.01211658509314204,
"recovery_ratio":0.9427474249101173,
"change":{
"total_cases":87345,
"active_cases":-100842,
"deaths":2115,
"recovered":186072,
"death_ratio":3.655106707928235e-5,
"recovery_ratio":0.0035880023182339738
}
},
I want to save data acquired from Volley, But lambda used in VolleyRequest function(which gets json data from server) blocks it.
How should I change local variable that is in outside of lambda?
Thanks in advance.
class ConDataforReturn( val title:String , val imgDataList: ArrayList<ConImgData>)
fun getConData(context: Context, idx : String):ConDataforReturn{
val params = HashMap<String,String>()
var cd = arrayListOf<ConImgData>()
var title =""
params.put("package_idx",idx)
Log.e("idx size",idx.length.toString())
VolleyRequest(context,params,"https://dccon.dcinside.com/index/package_detail") { response ->
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
Log.d("title",title)//Prints right data
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
cd.add(ConImgData(v.getString("title"), v.getString("ext"), v.getString("path")))
}
}
return ConDataforReturn(title,cd)//returns ConDataforReturn("",arrayListOf<ConImgData>())
}
Here the the code from were you are calling this method
getConData(this, "id") { condata ->
}
Now, your method look like this,
fun getConData(context: Context, idx : String, returnConData : (condata : ConDataforReturn) -> Unit){
val params = HashMap<String,String>()
var cd = arrayListOf<ConImgData>()
var title =""
params.put("package_idx",idx)
Log.e("idx size",idx.length.toString())
VolleyRequest(context,params,"https://dccon.dcinside.com/index/package_detail") { response ->
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
Log.d("title",title)//Prints right data
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
cd.add(ConImgData(v.getString("title"), v.getString("ext"), v.getString("path")))
}
returnConData(ConDataforReturn(title,cd)) //returns ConDataforReturn("",arrayListOf<ConImgData>())
}
}
Working on an Android application, using KOTLIN. Inside my activity, I'm accessing the Merriam-Webster Dictionary JSON file from a URL (Github). The file's pretty big, to say the least. I want to display the "Word Of The Day" randomly on my TextView, which means I have to get a random key from the JSON so I can display its value.
How do I do this?
Thank you in advance
DictionaryActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dictionary)
fetchJson()
init()
}
private fun init(){
val email = intent.extras!!.getString("email", "")
welcomeTxv.text = "Welcome, " + email.substringBefore("#")
}
// Fetching (url) and searching through json.
private fun fetchJson(){
println("Attempting to fetch Json file")
val url = "https://raw.githubusercontent.com/matthewreagan/WebstersEnglishDictionary/master/dictionary.json"
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object: Callback{
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
#Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") val jsonObject = JSONObject(body)
loadingCircle.visibility = if (loadingCircle.visibility == View.VISIBLE){
View.INVISIBLE
} else{
View.VISIBLE
}
searchBtn.setOnClickListener {
if (searchField.text.isNotEmpty() && jsonObject.has(searchField.text.toString())){
meaningTextView.setTextColor(WHITE)
meaningTextView.text = jsonObject.optString(searchField.text.toString())
databaseAction()
}else{
meaningTextView.setTextColor(RED)
meaningTextView.text = "The word you searched for could not be found."
}
}
}
override fun onFailure(call: Call, e: IOException) {
Toast.makeText(applicationContext, "Request failed", Toast.LENGTH_SHORT).show()
}
})
}
fun databaseAction(){
val email = intent.extras!!.getString("email", "")
val userIdentification = email.toString()
val database = FirebaseDatabase.getInstance()
val myRef = database.getReference(userIdentification.substringBefore("#"))
val sdf = SimpleDateFormat.getDateInstance()
val currentDate = sdf.format(Date())
val stf = SimpleDateFormat.getTimeInstance()
val currentTime = stf.format(Date())
myRef.push().setValue(searchField.text.toString() + " " + currentDate + " " + currentTime)
}
This does not work (crashes the application):
val keys = arrayOf(jsonObject.keys())
val randomNumber = (0..1000).random()
val randomKey = keys[randomNumber]
application crashed because index out of bound exception throws...
// keys() document from Android doc page
open fun keys(): MutableIterator<String!>
keys() return type of MutableIterator
for more info: Android JSON document link
keys type is array of a MutableIterator, and its' length is 1
so, the expression below may throw index out of bound exception if randomNumber is not 0
val randomKey = keys[randomNumber] // opps if randomNumber is not zero
to get the random key from keys:
// shuffled() will return a list with random order
// first() take the first element of the list
val randomKey = xxxx.keys.shuffled().first()
no Android environment in my hand, here is my guess
val randomKey = jsonObject.keys().asSequence().toList().shuffled().first()
hope this gives you a little help :)
I am new to Android and Kotlin and am currently working on a centralized API router class.
To achieve this I am using the Fuel Framework.
For the doAsync function, I use the Anko for Kotlin library.
To retrieve an authorization token from the API I currently use this method:
private fun Login(username: String, password: String, callback: (Map<Boolean, String>) -> Unit) {
"/auth/token.json".httpPost()
.header(mapOf("Content-Type" to "application/json"))
.body("""{"username":"$username", "password":"$password"}""", Charsets.UTF_8)
.response { request, response, result ->
request.headers.remove("Accept-Encoding")
when (result) {
is Result.Failure -> {
// val data = result.get()
val ex = result.getException()
val serverResponseJson = response.data.toString(Charsets.UTF_8)
var exceptionMessage = ex.message
val jelement = JsonParser().parse(serverResponseJson)
val jobject = jelement.asJsonObject
val serverResponseError = if (jobject.has("Error")) jobject.get("Error").asString else jobject.get("detail").asString
callback(mapOf(Pair(false, serverResponseError)))
}
is Result.Success -> {
val data = result.get()
val returnJson = data.toString(Charsets.UTF_8)
Log.println(Log.ASSERT, "RESULT_LOGIN", returnJson)
callback(mapOf(Pair(true, returnJson)))
}
}
}
}
I invoke this login method at
val btnLogin = findViewById<Button>(R.id.btn_login)
btnLogin.setOnClickListener { _ ->
doAsync {
val username = findViewById<EditText>(R.id.input_username_login)
val password = findViewById<EditText>(R.id.input_password_login)
Login(username.text.toString(), password.text.toString()) {
// Request was successful
if (it.containsKey(true)) {
// Parse return Json
// e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
val jelement = JsonParser().parse(it.getValue(true))
val jobject = jelement.asJsonObject
// save field for class-scope access
Constants.token = jobject.get("token").asString
Constants.id = jobject.get("id").asString
}
else{
Toast.makeText(this#LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
}
}
}[30, TimeUnit.SECONDS]
var test = Constants.id;
}
In a separate Constants class, I store the token and id like this:
class Constants {
companion object {
val baseUrl: String = "BASE_URL_TO_MY_API"
val contentTypeJson = "application/json"
lateinit var STOREAGE_PATH: String
// current user details
lateinit var id: String
lateinit var token: String
lateinit var refresh_token: String
// logged in User
lateinit var user: User
}
How do I make sure that the test variable is set after the asynchronous task is done? Currently, I run into
lateinit property id has not been initialized
I have come across the option to limit the task to a timeout such as I have done with [30, TimeUnit.SECONDS], unfortunately, this did not help.
Thanks for the help! Cheers.
I think the problem is where you want to access the result:
val btnLogin = findViewById<Button>(R.id.btn_login)
btnLogin.setOnClickListener { _ ->
doAsync {
val username = findViewById<EditText>(R.id.input_username_login)
val password = findViewById<EditText>(R.id.input_password_login)
var test: String? = null
Login(username.text.toString(), password.text.toString()) {
// Request was successful
if (it.containsKey(true)) {
// Parse return Json
// e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
val jelement = JsonParser().parse(it.getValue(true))
val jobject = jelement.asJsonObject
// save field for class-scope access
Constants.token = jobject.get("token").asString
Constants.id = jobject.get("id").asString
}
else{
Toast.makeText(this#LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
}
}
test = Constants.id // here test variable surely set if result was successful, otherwise it holds the null value
test?.let{
resultDelivered(it)
}
}[30, TimeUnit.SECONDS]
}
fun resultDelivered(id: String){
// here we know that the async job has successfully finished
}