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

React PWA与Android WebView原生Wrapper双向通信问题求助

解决React PWA与Android WebView双向通信的可行方案

针对你遇到的addJavascriptInterface未生效的问题,下面提供几个经过验证的双向通信实现方案,附具体代码示例:

方案一:修复addJavascriptInterface配置问题

很多时候该方案失效是因为配置遗漏,按以下步骤检查并实现:

Android端配置

  1. 创建供JS调用的接口类,必须添加@JavascriptInterface注解:
class AndroidBridge(private val context: Context) {
    // 供JS调用的方法
    @JavascriptInterface
    fun sendLocationToPWA(lat: Double, lng: Double) {
        Log.d("AndroidBridge", "位置信息已传递给PWA: $lat, $lng")
    }

    @JavascriptInterface
    fun showToast(message: String) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
    }
}
  1. 配置WebView,启用JS并注入接口:
webView.settings.javaScriptEnabled = true
// 注入接口,"AndroidBridge"是JS中访问的全局对象名
webView.addJavascriptInterface(AndroidBridge(this), "AndroidBridge")
// 若PWA为HTTPS、本地资源为HTTP,需开启混合内容支持
webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW

React PWA端调用Android方法

在React组件中直接通过全局对象调用:

// 调用Android的showToast方法
window.AndroidBridge?.showToast("来自PWA的消息")

// 接收Android主动传递的位置信息(Android端通过evaluateJavascript触发)
window.receiveLocation = (lat, lng) => {
    console.log("从Android获取到位置:", lat, lng)
    // 更新React组件状态
    setLocation({ lat, lng })
}

注意事项:

  • 接口类方法必须为public,且必须添加@JavascriptInterface注解
  • 避免在接口方法中直接操作UI,需通过runOnUiThread切换到主线程
  • Android 4.2及以上版本才支持该注解,低版本存在安全风险

方案二:使用evaluateJavascript + WebChromeClient实现双向通信

该方案兼容性更好,且规避了addJavascriptInterface的安全隐患:

Android端实现

  1. 设置WebChromeClient拦截JS的prompt请求,用于JS调用Android:
webView.webChromeClient = object : WebChromeClient() {
    override fun onJsPrompt(
        view: WebView?,
        url: String?,
        message: String?,
        defaultValue: String?,
        result: JsPromptResult?
    ): Boolean {
        // 约定消息格式为"action:params",解析后处理
        if (message?.startsWith("pwa:") == true) {
            val parts = message.split(":")
            val action = parts[1]
            val params = parts.getOrNull(2)
            when (action) {
                "requestLocation" -> {
                    // 调用原生位置服务获取坐标
                    val lat = 39.9042
                    val lng = 116.4074
                    // 调用PWA的JS方法返回结果
                    webView.evaluateJavascript("window.handleLocationResult($lat, $lng)", null)
                    result?.confirm()
                    return true
                }
                "showToast" -> {
                    params?.let { Toast.makeText(this@MainActivity, it, Toast.LENGTH_SHORT).show() }
                    result?.confirm()
                    return true
                }
            }
        }
        return super.onJsPrompt(view, url, message, defaultValue, result)
    }
}

// Android主动调用PWA方法
fun sendDataToPWA(data: String) {
    webView.evaluateJavascript("window.handleAndroidData('$data')", null)
}

React PWA端实现

// JS调用Android方法,通过prompt传递指令
const callAndroidMethod = (action, params) => {
    const message = `pwa:${action}:${params}`
    prompt(message)
}

// 接收Android传递的数据
window.handleAndroidData = (data) => {
    console.log("从Android收到数据:", data)
}

// 接收Android返回的位置结果
window.handleLocationResult = (lat, lng) => {
    console.log("位置结果:", lat, lng)
    setLocation({ lat, lng })
}

// 使用示例
callAndroidMethod("requestLocation", "")
callAndroidMethod("showToast", "Hello from PWA")

方案三:使用WebMessagePort(Android 7.0+)

这是Android官方推荐的现代双向通信方式,支持消息通道:

Android端配置

webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        // 创建消息通道
        val channel = webView.createWebMessageChannel()
        // 向PWA发送端口(需指定PWA域名)
        webView.postWebMessage(WebMessage("init", arrayOf(channel[1])), Uri.parse("你的PWA域名"))
        // 监听PWA发送的消息
        channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() {
            override fun onMessage(port: WebMessagePort?, message: WebMessage?) {
                val data = message?.data
                if (data == "requestLocation") {
                    // 返回位置信息
                    port?.postMessage(WebMessage("{\"lat\":39.9042, \"lng\":116.4074}"))
                }
            }
        })
    }
}

React PWA端实现

// 监听Android发送的消息通道
window.addEventListener("message", (event) => {
    if (event.data === "init") {
        const port = event.ports[0]
        window.androidPort = port
        // 监听端口消息
        port.onmessage = (e) => {
            const location = JSON.parse(e.data)
            console.log("通过WebMessagePort获取位置:", location)
            setLocation(location)
        }
    }
})

// 向Android发送消息
const sendMessageToAndroid = (message) => {
    window.androidPort?.postMessage(message)
}

// 使用示例
sendMessageToAndroid("requestLocation")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:55:28