一,需求前提:
网页上有一个挂机任务,当用户点击手机返回键,home键,菜单键,要通知网页,然后进行一系列操作,然后告知客户端下一步操作
二,首先我们知道js 与android相互调用的方式
1,js掉用android方法
①
webView.addJavascriptInterface(new InJsAndroid(), "injs_android");
②
final class InJsAndroid{
@JavascriptInterface
public void gotoVideo() {}
}
2,Android调用js方法
① 不带参数
webView.loadUrl("javascript:onHome()");
② 带参数
webView.loadUrl("javascript:onHome('"+outbox+"')");
所以,想要客户端执行操作告诉网页并有回调,最简单最傻瓜式的操作:先调用网页方法执行 2方法,然后网页一系列操作后执行 1方法返回客户端
三,其次定位挂机任务界面,判断挂机界面 ,只在该界面有拦截,有两种方式
① 网页加载的url中添加特殊字符,在客户端shouldOverrideUrlLoading 方法时,判断一下,加个状态值,当点击返回时就以此值做判断
② 加载网页时加一个新方法,同样记录状态值
我们在前进后退页面时都会执行shouldOverrideUrlLoading方法,这样就可以知道是那个界面了
四,然后设置监听键方式:
打开百度,查到的最多的就是
① onKeyDown()
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
可惜 该方法里设置只在activity有用,在fragment中根本没这个方法,而且home和menu对应的 KEYCODE_HOME,KEYCODE_MENU都没作用
② onBackPressed()
@Override
public void onBackPressed() {
if (webView!= null && webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
只能针对返回键,在fragment中没这个方法
③ setOnKeyListener()
webView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
webView.goBack();
return true;
}
}
return false;
}
});
这个还可以,能实现在fragment中返回操作,但同样不能实现home键,菜单键的监听拦截
④ onUserLeaveHint()
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
Toast.makeText(this, "onUserLeaveHint", Toast.LENGTH_SHORT).show();
}
据说这个可以监听home 键 ,先不管能不能用,在fragment下也是没有这个方法
⑤最后,网上很多资料都认为下面这个方法可行,能监听home键,菜单键 ,代码如下
// 创建方法注册广播
if (getContext() != null) {
getContext().registerReceiver(homeKeyEventReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
//监听home键和菜单键
private BroadcastReceiver homeKeyEventReceiver = new BroadcastReceiver() {
String REASON = "reason";
String HOMEKEY = "homekey";
String RECENTAPPS = "recentapps";
@Override
public void onReceive(Context context, Intent intent) {
if (onHookState && !onHookHomeState) {
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
String reason = intent.getStringExtra(REASON);
if (TextUtils.equals(reason, HOMEKEY)) {
// 点击 Home键
Log.e("ddddddddddd", "Home");
onHookHomeState = true;
webView.loadUrl("javascript:onHome()");
} else if (TextUtils.equals(reason, RECENTAPPS)) {
// 点击 菜单键
Log.e("ddddddddddd", "菜单键");
onHookHomeState = true;
}
}
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
//销毁方法里面记得反注册
try {
if (getContext() != null && homeKeyEventReceiver != null)
getContext().unregisterReceiver(homeKeyEventReceiver);
} catch (Exception ignored) {
}
}
onHookState 是指定该页面的标识,如果不是该网页,不监听。onHookHomeState 是标识是否点击了home,菜单键,可以直接忽略,看逻辑,确实实现了监听。
但是,但是,通过测试发现有如下几个问题:
① 每次点击home键都会执行该广播,不管是回到主界面,还是显示,这个好解决,加标识即可,如上onHookHomeState (未完善)
②点击了一次后,再次点击,广播好像不起反应了,不会触发了,可以尝试修改注册与反注册的时机,每次重新打开和暂停都注册与反注册
@Override
protected void onResume() {
super.onResume();
//注册
registerHomeKeyReceiver(this);
}
@Override
protected void onPause() {
// 解除
unregisterHomeKeyReceiver(this);
super.onPause();
}
③ 点击回到主界面之后,再次点击home键是先执行该方法,而不会判断有没有打开,这个比较坑了,如果我打开别的应用,监听还在。
④该方式只能监听,不能拦截,点击home键,直接退到手机主界面了,根本没拦截到。
回到最初的需求,想要拦截home键,然后让网页做操作,然后返回啊,到最后查了很多地方,发现都不可行。
无能为力了
最后的办法是改需求,没错 ,就是改需求
理直气壮的告诉产品,home键和菜单键是系统级别的 ,没法子拦截,只能监听,然后做别的操作

把需求改为 返回键可以监听,与网页交互可正常回调,如果点击了home键和菜单键 直接告诉网页,客户端该回首页回首页,不做拦截,响应网页回调操作
最终效果 :在onPause()里判断下
@Override
public void onPause() {
super.onPause();
if (onHookState){
webView.loadUrl("javascript:onHome()");
}
}
以此记录一下,网上的方法代码真的是五花八门,各种方法都有,不管对不对,转发,写就完了,很多记录的不清不楚的,只写一半,还有小细节都不标明,需要一点一点的测试,有坑得跳,
本文探讨了JS与Android的交互方式,包括JS调用Android方法和Android调用JS方法的具体实现。同时,深入讨论了在Android中监听手机按键(如返回键、Home键、菜单键)的多种方法及其局限性,特别关注了WebView环境下按键监听的实现与挑战。

606

被折叠的 条评论
为什么被折叠?



