Android Kotlin:通过JavascriptInterface修改WebView URL报错求助
Android WebView通过JavascriptInterface调用loadUrl报错解决
问题描述
使用Kotlin开发Android WebView应用,尝试通过JavascriptInterface调用loadUrl修改WebView的URL时,出现错误:Uncaught Error: Java exception was raised during method invocation。调用返回字符串的JavascriptInterface方法可以正常工作,但执行webview.loadUrl就触发异常。
相关代码
WebAppInterfaced.kt
package com.example.barangkalearninghub import android.content.Context import android.webkit.JavascriptInterface import android.webkit.WebView class WebAppInterfaced(val webview: WebView) { @JavascriptInterface fun PageRedirect(newUri: String) { webview.loadUrl(newUri) } }
MainActivity.kt
package com.example.barangkalearninghub import android.annotation.SuppressLint import android.os.Bundle import android.webkit.WebChromeClient import android.webkit.WebView import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat @SuppressLint("SetJavaScriptEnabled") class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_main) 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 } val webView: WebView = findViewById(R.id.webViewMain) webView.webChromeClient = WebChromeClient() WebView.setWebContentsDebuggingEnabled(true) val jsInterface: WebAppInterfaced = WebAppInterfaced(webView); webView.addJavascriptInterface(jsInterface, "WebAppInterfaced") webView.settings.databaseEnabled = true webView.settings.allowFileAccess = true webView.settings.javaScriptEnabled = true webView.settings.domStorageEnabled = true webView.settings.useWideViewPort = true webView.loadUrl("file:///android_asset/index.html") } }
assets/index.html
window.addEventListener('load', function(){ var p = $("#demo"); p.html("hello jquery android"); setTimeout(function(){ WebAppInterfaced.PageRedirect("dashboard.html"); }, 5000); });
解决方案
核心原因
JavascriptInterface标注的方法运行在WebView的后台线程(非主线程),而Android中所有UI组件的操作必须在主线程执行,直接调用webview.loadUrl会触发CalledFromWrongThreadException,这就是报错的根源。
修改代码
将loadUrl操作切换到主线程执行,同时确保传入的URL是完整的asset路径(避免相对路径解析问题):
修改后的WebAppInterfaced.kt
package com.example.barangkalearninghub import android.webkit.JavascriptInterface import android.webkit.WebView class WebAppInterfaced(val webview: WebView) { @JavascriptInterface fun PageRedirect(newUri: String) { // 用WebView的post方法将操作切换到主线程 webview.post { // 拼接完整的asset文件路径 val fullUrl = "file:///android_asset/$newUri" webview.loadUrl(fullUrl) } } }
另一种实现(通过Activity主线程)
如果需要依赖Activity上下文,也可以通过runOnUiThread实现:
package com.example.barangkalearninghub import android.webkit.JavascriptInterface import android.webkit.WebView import androidx.appcompat.app.AppCompatActivity class WebAppInterfaced(val activity: AppCompatActivity, val webview: WebView) { @JavascriptInterface fun PageRedirect(newUri: String) { activity.runOnUiThread { val fullUrl = "file:///android_asset/$newUri" webview.loadUrl(fullUrl) } } }
对应MainActivity中的初始化:
val jsInterface = WebAppInterfaced(this, webView)
验证说明
修改后,Javascript调用PageRedirect时,loadUrl操作会在主线程执行,既符合Android的UI线程规则,又能正确加载assets目录下的目标HTML文件,不会再触发异常。
内容的提问来源于stack exchange,提问作者exejee
相关产品推荐
相关产品推荐

