0

C#/Java Dev trying to learn Kotlin here.

I'm pinging a website from my Kotlin app, but I'm unable to fetch the awaited Task result. 'pingResponse' (inside the awaited function) returns true as expected. But 'pingResult' (part of the String Builder) always returns false. What could be the correct way to retrieve the result?

package com.android.ews2

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.telephony.TelephonyManager
import android.widget.TextView
import kotlinx.coroutines.*
import java.io.PrintWriter
import java.io.StringWriter
import java.lang.Runnable
import java.net.InetAddress
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

   ObtenerPhoneState(this.applicationContext,this);

    val textMultiLine = findViewById<TextView>(R.id.textMultiLine);

    val mainHandler = Handler(Looper.getMainLooper())

    mainHandler.post(object : Runnable {
        override fun run() {
            refreshUserData(textMultiLine);
            mainHandler.postDelayed(this, 15000)
        }
    })

}

fun refreshUserData(textMultiLine : TextView) {

    var sb = StringBuilder();

    val sdf = SimpleDateFormat("dd/M/yyyy hh:mm:ss")
    val currentDate = sdf.format(Date())

    sb.append(currentDate.toString() + "\n");

    val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager

    sb.append("simOperatorName: " + telephonyManager.simOperatorName+ "\n");

    sb.append("dataActivity: " + telephonyManager.dataActivity + "\n");

    sb.append("callState: " + telephonyManager.callState + "\n");

    sb.append("dataState: " + telephonyManager.dataState + "\n"); 

//This always returns false

    sb.append("pingResult: " + ping() + "\n");

    textMultiLine.text = sb.toString()

}



private fun ping(): Boolean = runBlocking  {

    var pingResponse = false;

    GlobalScope.launch(Dispatchers.IO)

{


    try {
        
        println("Pinging...")

        pingResponse = InetAddress.getByName("www.google.com").isReachable(500);

//This returns true, as expected

        println("Ping result: " + pingResponse);

    } catch (ex: Exception) {

        val sw = StringWriter()
        ex.printStackTrace(PrintWriter(sw))
        val exceptionAsString = sw.toString()
        println(exceptionAsString)

    }

 }
    return@runBlocking pingResponse;
}

}

Things I tried:

  1. Using Kotlin Coroutines
  2. Using GlobalScope.Launch
  3. Using Suspend Functions
  4. Using RunBlocking

On these experiments, I got funny errors like 'Type mismatch: expected Unit, found Boolean' or 'android.os.NetworkOnMainThreadException'.

Sergio
  • 27,326
  • 8
  • 128
  • 149
Felipe La Rotta
  • 343
  • 3
  • 13

1 Answers1

0

You need to launch a coroutine, call the function in different context, and then use a result. It will look similar to this:

// launching a coroutine in lifecycleScope, by default it uses Dispatchers.Main context,
// so we can update Views in it
fun refreshUserData(textMultiLine : TextView) = lifecycleScope.launch {
    var sb = StringBuilder()
    // ...
    sb.append("pingResult: " + ping() + "\n");

    textMultiLine.text = sb.toString()
}

// using withContext() we are switching the context of function execution
// it will execute in background thread
private suspend fun ping(): Boolean = withContext(Dispatchers.IO)  {

    var pingResponse = false

    try {
        println("Pinging...")
        pingResponse = InetAddress.getByName("www.google.com").isReachable(500)
        println("Ping result: $pingResponse")

    } catch (ex: Exception) {
        val sw = StringWriter()
        ex.printStackTrace(PrintWriter(sw))
        val exceptionAsString = sw.toString()
        println(exceptionAsString)
    }

    return@withContext pingResponse
}

To use lifecycleScope add dependency:

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:$2.4.0'
Sergio
  • 27,326
  • 8
  • 128
  • 149