移动端网页监听返回键

编程入门 行业动态 更新时间:2024-10-10 13:23:50

移动端<a href=https://www.elefans.com/category/jswz/34/1771338.html style=网页监听返回键"/>

移动端网页监听返回键

一、背景

公司项目因为一些原因,需要把某些页面用 h5 来开发,我们做的是机顶盒上的项目,要用遥控器来操作,在电脑浏览器上调试好项目后就打算测试下功能了,结果发现遥控器上某些按键在网页上居然监听不到按键事件,例如返回键,菜单键,home 键等。

二、分析

就拿返回键来验证问题好了,下意识会觉得键盘的 ESC 就相当于返回键了,因为可以用键盘的 ESC 控制机顶盒返回,实际并不是,在 PC 端可以监听到键盘上的 ESC 按键,但是机顶盒上是监听不到返回键的,猜测是否是厂家修改了rom,但测试发现手机上也是监听不到的,结论是移动端浏览器就是这么设计的。
为什么在移动端上监听不到返回键,这样设计其实是合理的,大致流程是设备硬件接收到遥控器红外信号后,会把按键事件分发给 framework 层 -> app 应用层 -> webview层,但是这流程中会有一部分按键被拦截,例如在 app 应用层就已经收不到 Home 键的事件了,在 webview 层收不到返回键、设置键、音量键等的按键了。
返回键、Home 键这么重要的按键,怎么能随意交给开发者处理!
为什么不能交给开发者处理?因为开发者得听产品的。
如果允许开发者完全控制返回键,可能会收到类似这样的产品需求:
1.用户进到我们的活动广告页面后,不允许他立即按返回键退出,要让用户最少看 10 秒才能退出;
2.用户打开我们的网页后,就不允许他按返回键退出了;
3.用户只要打开了我们的网页,就不允许他按任何按键退出了,Home 键也不行!!
想啥呢朋友,用户是上帝,手机又不是你的,人家不小心用手机浏览器打开了你的网页,你不让走了?

手机自带浏览器及 webview 加载的网页上收不到返回键监听是因为浏览器是一个公共的 app,没有人去干涉它,那自然不能允许开发者在返回键上做文章,但是如果你是在 app 里嵌入网页,有能力干预一些事件且能保证产品流程没问题,你就可以通过 native 和 js 相结合的方式实现在网页里控制返回键。

三、实现方案

1.让 app 的开发者在网页窗口页面实现如下控制

...private WebView webview;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web);webview = findViewById(R.id.webView);webview.getSettings().setJavaScriptEnabled(true);String url = getIntent().getStringExtra("url");}@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && webview != null) {if (event.getAction() == KeyEvent.ACTION_DOWN) {if (loadError) {finish();return true;}callWebBack();}return true;}return super.dispatchKeyEvent(event);}public void callWebBack() {JSONObject jsonObject = new JSONObject();try {jsonObject.put("which", 23);jsonObject.put("type", "keydown");} catch (JSONException localJSONException) {localJSONException.printStackTrace();}WebView localWebView = this.webview;String stb = "javascript: window.event=" +jsonObject +";if(typeof document.myBack=='function'){document.myBack(" +jsonObject +")}";localWebView.evaluateJavascript(stb, new ValueCallback<String>() {public void onReceiveValue(String value) {if ("null".equals(value)) { // 如果网页里没写document.myBack方法,代表不控制返回页面,由native处理WebActivity.this.goBack();} else if (value.equals("0")){// 否则判断是否已经到了根页面,如果是就关闭 native 页面if (webview != null && !webview.canGoBack()) {WebActivity.this.finish();}}// 如果返回了别的值,native 不做任何处理}});}private void goBack() {runOnUiThread(new Runnable() {@Overridepublic void run() {if (webview != null && webview.canGoBack()) {webview.goBack();} else {finish();}}});}
...

如果网页里未定义 document.myBack 方法,就由 native 来控制网页的返回事件;
如果定义了方法,返回 0,当网页回退到根页面时,会由 native 控制返回键退出当前页面;
如果返回其它值,native 就不管返回键了,一般用于这种情况:app 提供退出当前 native 页面的接口方法,网页里通过 js 调用 native 方法来关闭 native 页面,native 就完全不管返回键了,但是这样其实是有风险的,因为一旦网页里流程控制出了问题(该调用 native 提供的关闭页面接口方法却没调用),就会出现用户按返回键关闭不了 native 页面了的问题。

2.网页里可以在页面 js 里加入如下方法
例如在vue里面,main.js 可以这么写

...
import router from './router'
document.myBack = () => {setTimeout(() => {router.back(-1)}, 10)return 0
};

这里为什么要设置个 10ms 的延时?因为当返回 0 时,网页里是先执行 back(-1),native 才去判断当前网页栈还能不能再回退,这会导致当用户在倒数第二个页面按返回键时,先回退到网页首页,native 再去判断当前还能不能回退,这时由于到首页了已经不能回退了,就会直接 finish 整个浏览器页面了,但是实际上这一次不应该关闭浏览器页面的,应该在网页首页按返回键时才 finish。
其实这个逻辑也可以在 native 层去控制,但是如果网页被多个 app 去加载,就得多个团队都实现这个逻辑,且两边沟通成本是很高的,不如在网页里一次处理好。
这样就实现了在网页里控制返回键,其它的音量键、菜单键等,只要 apk 应用层能接收到,都可以通过这种方案来实现网页监听。

更多推荐

移动端网页监听返回键

本文发布于:2024-02-24 21:17:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1696680.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:网页

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!