skip to Main Content

I created an android app and loading an html file on android webView. Which is loaded successfully and working fine.

class MainActivity : AppCompatActivity() {

    private lateinit var myAndroidWebView: WebView;
    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        setWebviewDetails();
    }

    private fun setWebviewDetails(){
        //if(!::myAndroidWebView.isInitialized){
        myAndroidWebView = findViewById(R.id.webView);
        //}
        myAndroidWebView.settings.javaScriptEnabled = true;
        myAndroidWebView.loadUrl("file:///android_asset/App/index.html");
        myAndroidWebView.addJavascriptInterface(WebAppInterface(this), "AndroidApp");
    }
    
    public fun testMessage(param: String){
        println("Interface call-2")
        myAndroidWebView.post(Runnable {
            val str = "xxxXXXXXXXXXXXXXx $param"
            myAndroidWebView.loadUrl("javascript:Application.UserInterface.sample('$str')")
        })
        println("Interface call-3")
    }
}

Now I want to send message to Android app to JS and vice versa.
I have a button in HTML and triggeting the function

public fun showToast(toast: String) {}

From HTML view by using, AndroidApp.showToast("hello");
Which is working fine and I am getting call from JS to Android interface function showToast()

Now on request from the JS I want to get some values from Android and send back to JS as well.
I have an interface, on trigger button from HTML I am getting call on the below interface function.
And trying to call a method in the MainActivity, public fun testMessage(param: String){} is triggered succssfully.

Issue:
I am trying to send data to JS by using,

myAndroidWebView.loadUrl("javascript:Application.UserInterface.sample('$str')")

Here I am getting error.

W/System.err: kotlin.UninitializedPropertyAccessException: lateinit property myAndroidWebView has not been initialized

How do I resolve it.
Thanks.

    /** Instantiate the interface and set the context  */

class WebAppInterface(private val mContext: Context) {
    var mainActivity:MainActivity = MainActivity();

    /** Show a toast from the web page  */

    @JavascriptInterface
    public fun showToast(toast: String) {
        println("Interface call-1")
        mainActivity.testMessage(mContext,toast);
    }
}

2

Answers


  1. lateinit property not initialized exception is thrown because you are trying to create an instance of MainActivity in WebInterface. var mainActivity:MainActivity = MainActivity();

    It is Android system’s job to create and load your activities. You should never try to initiate an activity.

    Here, a rough improvement of your code. Try to adapt it to your needs.

    interface JsCommunicator {
      fun testMessage(param: String)
    }
    
    class WebAppInterface(private val communicator: JsCommunicator) {
      @JavascriptInterface
      fun showToast(toast: String) {
        communicator.testMessage(toast)
      }
    }
    
    class YourMainActivity : JsCommunicator {
      // ...
    
      private lateinit var myAndroidWebView: WebView
      override fun testMessage(param: String) {
        println("Interface call-2")
        myAndroidWebView.post(Runnable {
          val str = "xxxXXXXXXXXXXXXXx $param"
          myAndroidWebView.loadUrl("javascript:Application.UserInterface.sample('$str')")
        })
        println("Interface call-3")
      }
    }
    
    Login or Signup to reply.
  2. You are accessing web-view without initialising it.
    call setWebviewDetails() first then testMessage() 
    or you can make webview nullable like this
    private var myAndroidWebView: WebView? = null;
    
    also you need to call startActivity() to create Activity not by 
    creating objects as this is framework class managed by Android 
    System.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search