0

As an example, let's assume for a project, I have a WebView instance I'm using in my main activity loading a local HTML file:

class MainActivity : AppCompatActivity() {
    lateinit var myWebView:WebView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        myWebView = findViewById(R.id.webview)
        myWebView.getSettings().setAllowContentAccess(true);
        myWebView.getSettings().setAllowFileAccess(true);
        myWebView.settings.javaScriptEnabled = true;
        myWebView.setWebChromeClient(WebChromeClient());
        myWebView.loadUrl("file:///android_asset/websrc/mainPage.html")
        myWebView.addJavascriptInterface(WebAppInterface(this), "Android")
    }    
}
class WebAppInterface(private val mContext: Context) {
    @JavascriptInterface fun getStatus() {
      MainActivity().myWebView.evaluateJavascript("setStatus('good to go!')", null)
      //Or: MainActivity().myWebView.loadURL("javascript:setStatus('good to go!')")
    }
}

I have a JavascriptInterface also, where from I would like to invoke Android.getStatus() in my HTML file:

<html>
  <head>
    ...
  </head>
  <body>
    <div id="status"></div> 
  </body>
  <script>
    document.addEventListener('DOMContentLoaded', function() {
        Android.getStatus()
    })
    function setStatus(status) {
      document.querySelector('#status').innerHTML = status
    }
  </script>
</html>

So far, I think understand why this wouldn't work. From what I've come to understand from answers like this or this, And especially in the documentation for WebView, I understand that the JavascriptInterface and the WebView are running on different threads, so something like setStatus() wouldn't be defined. So far, I've tried using runOnUiThread and Handler(). See an example for runOnUiThread:

@JavascriptInterface fun getStatus() {
      MainActivity().runOnUiThread(
                object : Runnable {
                    override fun run() {
                        MainActivity().myWebView.evaluateJavascript("setStatus('good to go!')", null)
                        //Or: MainActivity().myWebView.loadURL("javascript:setStatus('good to go!')")
                    }
                }
            )
    }

This (and use of Handler), however, gives me: E/AndroidRuntime: FATAL EXCEPTION: JavaBridge and lateinit property myWebView has not been initialized. I really don't understand why. Should mention I'm new to Kotlin and Android.

Any help?

1 Answers1

0

All I needed was to pass myWebView to the JavaScript interface along with this and use Runnable...

Creating the JS interface:

myWebView.addJavascriptInterface(WebAppInterface(this, myWebView), "Android")

And then inside a @JavascriptInterface function:

myWebView.post(Runnable {
            myWebView.loadUrl("javascript:customFunction()")
        })