You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中WebView JS接口无法正常工作问题排查求助

问题排查与修复方案

让我帮你梳理代码里的关键问题,这些问题直接导致了你拿到的Intent结果为null:

1. WebAppInterface 类的核心错误

你的WebAppInterface存在构造函数和回调持有逻辑的问题:

  • 类里的fun WebAppInterface(context: Context)不是有效的构造函数,属于冗余代码;
  • 主构造函数传入的listener没有被保存为类成员变量,导致getID方法无法访问外部的回调;
  • getID方法错误地把listener作为方法参数,JS调用时根本不会传递这个参数,自然无法触发回调逻辑。

2. MainActivity 里的两处小错误

  • 布局绑定类名写错:ActivityPayBinding应该是ActivityMainBinding,否则会导致WebView无法正常初始化;
  • setResult(RESULT_OK)没有传递携带数据的Intent,正确写法需要把封装好数据的Intent一起传入,不然调用方拿到的就是空数据。

3. PHP 中 Script 标签写法错误

带有src属性的<script>标签内部不能写代码,浏览器会直接忽略内部内容,必须把外部脚本引入和内联脚本分开写。


修正后的代码

MainActivity.kt

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import sbs.pros.app.databinding.ActivityMainBinding

typealias IDListener = (qr: String) -> Unit

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 修正布局绑定类名
        binding = ActivityMainBinding.inflate(layoutInflater)
        val webView = binding.webView
        val webSettings: WebSettings = webView.settings
        
        webSettings.javaScriptEnabled = true
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.builtInZoomControls = false
        
        webView.webViewClient = WebViewClient()
        webView.webChromeClient = WebChromeClient()
        
        webView.addJavascriptInterface(
            WebAppInterface(this) { id ->
                Log.d("MainActivity", "Received ID from JS: $id")
                // 封装数据并返回给调用方
                val answerIntent = Intent().apply {
                    putExtra("pay", id)
                }
                // 修正setResult,传递携带数据的Intent
                setResult(RESULT_OK, answerIntent)
                finish()
            }, 
            "AndroidInterface"
        )
        
        webView.setInitialScale(160)
        webView.loadUrl("https://pros.sbs/payment/create_payment.php?apicall=one_address")
        setContentView(binding.root)
    }
}

class WebAppInterface internal constructor(
    private val mContext: Context,
    private val listener: IDListener // 保存外部传入的回调
) {
    @JavascriptInterface
    @SuppressWarnings("unused")
    fun getID(id: String?) {
        id?.let {
            Log.d("WebAppInterface", "ID received: $it")
            listener(it) // 触发外部回调
        }
    }
}

create_payment.php

<!-- 分开引入外部脚本和内联脚本 -->
<script src="javascript.js"></script>
<script>
function giveID(id) {
    AndroidInterface.getID(id);
}
</script>
<?php
if(null !== filter_input(INPUT_GET, 'apicall')){
    switch(filter_input(INPUT_GET, 'apicall')){
        case 'one_address':
?>
<script src="javascript.js"></script>
<script>
giveID('some_id');
</script>
<?php
        break;
    }
}

额外注意事项

  • 可以添加Log日志,确认JS是否成功调用了Android的getID方法;
  • 如果页面是HTTPS,要确保没有混合内容问题(比如JS是HTTP资源),测试阶段可以临时设置webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW,正式环境建议统一用HTTPS;
  • 确保JS调用的方法名getID和Android端的方法名完全一致(大小写敏感)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 23:52:35