(I'm an Android newbie.)
Goal: When a message is received from the HTML page's JavaScript, switch to a different activity.
Error: Unresolved reference @MainActivity
The file MainActivity.kt exists in the same directory with class name MainActivity. Thank you!
FILE: WebViewActivity.kt
package io.github.g00fy2.quickiesample
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat.startActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
class WebViewActivity : AppCompatActivity() {
public class JsObject {
@JavascriptInterface
public fun msg(): String {
return "From Android!"
}
@JavascriptInterface
fun postMsg(msg: String) {
// ERROR from this@MainActivity
val mainActivityIntent = Intent(this@MainActivity, MainActivity::class.java)
mainActivityIntent.putExtra("postMsg", msg);
startActivity(mainActivityIntent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
....
}
}
Your problem is Not Android, but OOP. You are trying to access WebViewActivity
object outside of it's scope, I mean JsObject
class has a new scope that can access nothing from your Activity
members, despite it is inside the class. You can make JsObject
as inner class, but I would not recommend to do so.
If you need a single method that has an ability to use Context
related methods you can pass the method of your WebViewActivity
methods as @JavascriptInterface
like below:
class WebViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
webView.addJavascriptInterface(this, "MessageReceiver")
}
@JavascriptInterface
fun postMsg(msg: String) {
val mainActivityIntent = Intent(this, MainActivity::class.java)
mainActivityIntent.putExtra("postMsg", msg);
startActivity(mainActivityIntent)
}
}
And another option is to make separate class to pass into WebView
, but actually calls nothing that related to a Context
. Instead provide a callback to an Activity
to control the call. Example:
interface MessageReceiver {
fun onMessageReceived(msg: String)
}
class JsObject(private val messageReceiver: MessageReceiver) {
@JavascriptInterface
fun msg(): String {
return "From Android!"
}
@JavascriptInterface
fun postMsg(msg: String) {
messageReceiver.onMessageReceived(msg)
}
}
class WebViewActivity : AppCompatActivity(), MessageReceiver {
private val jsObject = JsObject(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onMessageReceived(msg: String) {
val mainActivityIntent = Intent(this@WebViewActivity, MainActivity::class.java)
mainActivityIntent.putExtra("postMsg", msg);
startActivity(mainActivityIntent)
}
}