You need to enable JavaScript to run this app. Android WebView实现JS Bridge时如何用Kotlin/Java判断网页JS函数是否存在
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView实现JS Bridge时如何用Kotlin/Java判断网页JS函数是否存在

Android WebView 原生侧检测指定JS函数存在性的实现方案

原生运行时和JS执行上下文是完全隔离的,无法直接在Kotlin/Java代码中跨域访问JS环境的变量定义,必须通过WebView提供的JS执行通道,将判断逻辑注入JS运行环境执行,再将检测结果回传给原生,完成后续兜底逻辑。

核心实现前提

  • 检测逻辑必须在页面完全加载完成后触发:所有JS函数的定义都依赖页面脚本的解析执行流程,需将检测动作绑定到WebViewClient的onPageFinished回调中,禁止在onPageStarted阶段执行,否则会出现100%的误判。
  • 检测逻辑需要保证无副作用:判断函数存在性时只做读取操作,不要修改页面全局变量、触发额外的页面逻辑。

可落地的实现方案

方案1:全版本兼容的JS接口回传模式

该方案适配所有Android版本的WebView,稳定性最高,不需要依赖高版本WebView的API特性。

  • 第一步:初始化WebView时注册专用的JS桥接接口,用于接收JS侧返回的检测结果:
webView.addJavascriptInterface(object {
    @JavascriptInterface
    fun onFuncCheckResult(funcExist: Boolean, targetFunc: String) {
        // JS接口回调默认在子线程,涉及UI操作需切回主线程
        mainHandler.post {
            if (!funcExist) {
                // 执行原生兜底逻辑
                runNativeFallback(targetFunc)
            }
        }
    }
}, "NativeFuncCheckHelper")
  • 第二步:在onPageFinished回调中注入检测JS片段:
override fun onPageFinished(view: WebView?, url: String?) {
    super.onPageFinished(view, url)
    // 替换为实际需要检测的目标JS函数名
    val checkTargetFunc = "jsBridgeEntry"
    val checkScript = """
        (function() {
            // 严格判断函数类型,避免未声明变量抛出ReferenceError
            val funcExist = typeof window.$checkTargetFunc === 'function';
            // 将结果回传给原生桥接对象
            window.NativeFuncCheckHelper.onFuncCheckResult(funcExist, "$checkTargetFunc");
        })();
    """.trimIndent()
    // 高版本WebView用evaluateJavascript执行
    view?.evaluateJavascript(checkScript, null)
    // 兼容API 19以下低版本WebView,用loadUrl方式执行JS
    // view?.loadUrl("javascript:$checkScript")
}

方案2:API 19+ 简化版结果回调模式

从Android 4.4(API 19)开始,WebView的evaluateJavascript接口可以直接拿到JS执行的返回值,不需要额外注册JS桥接对象,代码逻辑更简洁。

override fun onPageFinished(view: WebView?, url: String?) {
    super.onPageFinished(view, url)
    val checkTargetFunc = "jsBridgeEntry"
    val checkScript = """
        (function() {
            return typeof window.$checkTargetFunc === 'function';
        })();
    """.trimIndent()
    view?.evaluateJavascript(checkScript) { checkResult ->
        // 回调默认在主线程,可直接处理业务逻辑
        val funcExist = checkResult.toBoolean()
        if (!funcExist) {
            runNativeFallback(checkTargetFunc)
        }
    }
}

常见踩坑规避

  • 严格使用typeof做类型判断:如果直接访问未声明的全局变量,JS会直接抛出ReferenceError导致执行中断,typeof操作符对未声明变量的判断会安全返回"undefined",不会触发报错。
  • 跨域iframe场景适配:如果需要检测的JS函数定义在子iframe的全局作用域,需要将检测脚本注入到对应iframe的执行上下文,仅在顶层window检测会出现漏判。
  • 避免污染全局作用域:检测JS片段需要用立即执行函数包裹,不要在全局作用域声明临时变量,避免和页面原有脚本产生变量冲突。

内容的提问来源于stack exchange,提问作者Gabyola Lim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.08 11:15:03