【问题标题】:How to consume backpress events in web app side in Android WebView?如何在 Android WebView 中的 Web 应用端使用 backpress 事件?
【发布时间】:2019-11-15 20:39:03
【问题描述】:

使用 JS 接口处理 Kotlin WebView,我的 Web 应用程序需要从本机端检测 KeyEvent.KEYCODE_BACK 事件,以便在呈现时关闭 Web 应用程序对话框。如果对话框被关闭,我应该在本机端什么都不做(返回 true 到 super),否则我需要完成 web 视图活动(返回 false 到 super)。为了抓住我的意图,请阅读下面的代码,我在我的自定义 WebView 上实现了作为线索,

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {

    if (event.action == KeyEvent.ACTION_DOWN) {
        when (keyCode) {
            KeyEvent.KEYCODE_BACK -> {

                this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                    if (it == "1") {
                        // "Web app consumed onDeviceBackPressed event!"
                    } else {
                        // "Web app did not consume onDeviceBackPressed event!"
                        // super.onKeyDown(keyCode, event) won't work
                    }
                })

                // I am required to make the return call wait
                // return true/false base on status returned by js func
            }
        }
    }
    return super.onKeyDown(keyCode, event)
}

但我知道异步等待超级调用是不可能的。我该如何以其他方式处理这种情况?

【问题讨论】:

    标签: javascript android kotlin web-applications webview


    【解决方案1】:

    您可以在等待 JS 的第一个按键按下事件期间使用 KeyEvent,然后在获得结果时重新使用它。

    我曾经对触摸事件使用过这样的技巧,所以它应该可以工作。

    var delayedKeyCode : Int? = null
    var delayedKeyEvent : KeyEvent? = null
    var keyDownJSResult : String? = null
    
    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (event.action == KeyEvent.ACTION_DOWN) {
            when (keyCode) {
                KeyEvent.KEYCODE_BACK -> {
                    // see if there's "result" provided from JS
                    keyDownJSResult?.let{
                        keyDownJSResult = null    // wipe out result so it's not triggered twice
                        if (it == "1") {
                            // "Web app consumed onDeviceBackPressed event!"
                            return true
                        } else {
                            // "Web app did not consume onDeviceBackPressed event!"
                            return super.onKeyDown(keyCode, event)
                        }
                    }
                    // otherwise store keyDown arguments for later and trigger JS
                    delayedKeyCode = keyCode
                    delayedKeyEvent = event
                    this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                         // when JS returns value, trigger this onKeyDown event again
                         val oldCode = delayedKeyCode
                         val oldEv = delayedKeyEvent
                         delayedKeyCode = null
                         delayedKeyEvent = null
                         keyDownJSResult = it
                         onKeyDown(oldCode, oldEv)
                    })
                    // always consume event when waiting for JS result
                    return true 
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }
    

    【讨论】:

    • Pawel 你可以看到我的回答。无需额外变量即可解决。
    • @SazzadHissainKhan 它可以,但我是在头顶写它,正如我所说,我将它用于触摸事件(更频繁地调用)并且我使用这些变量来防止额外的触摸设置时触发的事件。我还从@JavaScriptInterface 重新调用触摸事件,所以方法范围内的变量对我没有好处。
    【解决方案2】:

    最后,我的一个小技巧解决了我的问题,

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    
        if (event.action == KeyEvent.ACTION_DOWN) {
            when (keyCode) {
                KeyEvent.KEYCODE_BACK -> {
                    this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                        if (it == "1") {
                            // consumed by web app, do nothing
                        } else {
                            // not consumed by web app, fire explicit back press event
                            mContext.onBackPressed()
                        }
                    })
                    return true
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-09
      • 1970-01-01
      相关资源
      最近更新 更多