如何在Android WebView的Web应用程序端使用backpress事件?

时间:2019-07-05 08:18:33

标签: javascript android kotlin web-applications webview

使用JS界面在Kotlin WebView上工作,我的Web应用程序需要从本机端检测KeyEvent.KEYCODE_BACK事件,以在显示时关闭Web应用程序对话框。如果取消了对话框,则我不应该在本地执行任何操作(将true还原为超级),否则,我需要完成网络视图活动(将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)
}

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

2 个答案:

答案 0 :(得分: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)
}

答案 1 :(得分:0)

最后,我有一点技巧可以解决我的问题,

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)
}