I am working on a project that consists of functions that retrieve and write to a html_data
variable and a timer that calls them every minute.
I save the previous html_data
to a prev_html_data
variable, and then when they are different, I send a notification.
The problem is that the variable is always an empty string (the way I initialized it), meaning it never gets overriden. html_data
works just fine, and is initialized the exact same way.
I even seperated everything into a function, so I can call it from the main class, but it still doesn't work.
Variable is always an empty string, no matter what I do... Every time I print it...
And also I forgot to mention, the html_data that I print in the timerRun() was never parsed by html_parse() for some reason, even though I call that function in fetchdata().
class MainActivity : AppCompatActivity() {
var unique_id = 1000
var html_data = ""
var prev_html_data = ""
lateinit var notificationManager: NotificationManager
lateinit var notificationChannel: NotificationChannel
lateinit var builder: Notification.Builder
private val channelId = "hallomotto"
private val description = "***** alert"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
fetchdata()
this.prev_html_data = html_data
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationChannel = NotificationChannel(channelId, description, NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.GREEN
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
builder = Notification.Builder(this, channelId)
.setContentTitle("Floria alert!!")
.setContentText("A new message has been posted (Floria is here!!!)")
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(this.resources, R.drawable.ic_launcher_background))
} else {
builder = Notification.Builder(this)
.setContentTitle("Floria alert!!")
.setContentText("A new message has been posted (Floria is here!!!)")
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(this.resources, R.drawable.ic_launcher_background))
}
val timer = Timer(true)
timer.schedule(object : TimerTask() {
override fun run() {
timerRun()
}
}, 60000, 60000)
}
private fun fetchdata() {
val volleyQueue = Volley.newRequestQueue(this)
val url = "*****"
val jsonRequest = JSONObject()
jsonRequest.put("key", "*****")
val jsonObjectRequest = JsonObjectRequest(
Request.Method.POST,
url,
jsonRequest,
{ response ->
val html_message = response.get("html_data")
html_data = html_message.toString()
display_html()
},
{ error ->
Toast.makeText(this, "Error has occurred when making the request", Toast.LENGTH_LONG).show()
Log.e("MainActivity", "load_error: ${error.localizedMessage}")
}
)
volleyQueue.add(jsonObjectRequest)
Log.v("JSON request", jsonRequest.toString())
}
private fun html_parse() {
html_data = """
<html>
<head>
</head>
<body>
""".trimIndent() + html_data
html_data += """
</body>
</html>
""".trimIndent()
}
private fun display_html() {
html_parse()
Log.v("Output", html_data)
val encoded_data = Base64.encodeToString(html_data.toByteArray(), Base64.NO_PADDING)
val webview = findViewById<WebView>(R.id.webview)
webview.loadData(encoded_data, "text/html", "base64")
}
private fun timerRun(){
fetchdata()
if(html_data != this.prev_html_data){
notificationManager.notify(unique_id, builder.build())
unique_id += 1
Log.e("Match 1", html_data);
Log.e("Match 2", this.prev_html_data)
}
this.prev_html_data = html_data
}
}
Volley requests are asynchronous. volleyQueue.add()
returns immediately, and the request will be processed some time later. You get the results in the response lambda.
As a result, when you call fetchdata()
, the data is not fetched yet by the time fetchdata()
returns. However, your current code expects that the data is fetched, because it attempts to read html_data
(this.prev_html_data = html_data
). That will still be the empty string.
Instead, you could have fetchdata()
fill in prev_html_data
as needed, such as on the first time you are loading the data, using the same response lambda as you are using to set up html_data
.