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
相关产品推荐
相关产品推荐

