内推

【长期有效】欢迎加入字节跳动我的团队:内推链接

写在前面:
这篇文章并没有提供屏蔽Home键的方法,仅仅是阐释一些原理,引发一些思考。


1.奇淫技巧的源泉:PhoneWindowManager#interceptKeyBeforeDispatching
拦截home键的思想大致由此发源。Input事件分发时,Service端就会过滤了一些事件,而Home的过滤,就在此方法。方法注释说明了,如果app是keyguard类型,则将home键事件派发给app。源码(API 19)如下:

if (keyCode == KeyEvent.KEYCODE_HOME) {... // If a system window has focus, then it doesn't make sense// right now to interact with applications.WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;if (attrs != null) {final int type = attrs.type;if (type == WindowManager.LayoutParams.TYPE_KEYGUARD|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {// the "app" is keyguard, so give it the keyreturn 0;}}...}

2.传说中的在onAttachedToWindow中调用getWindow().setType设置Window Type
方式如下:

    @Overridepublic void onAttachedToWindow() {getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);super.onAttachedToWindow();}

本人基于4.4(API 19)及以上系统版本进行测试,都报异常:

java.lang.IllegalArgumentException: Window type can not be changed after the window is added.

所以,这种方式并不可行。
并且,如果你的compileSdkVersion >= 21,TYPE_KEYGUARD这种Window类型都没有了…

3.思考IllegalArgumentException: Window type can not be changed after the window is added
报完错之后有种想法,既然在onAttachedToWindow方法中设置type不行,那在onCreate中或者onResume中,这两个生命周期方法调用时期早于onAttachedToWindow,可以一试。
然而发现并不行。在onKeyDown中打个断点,发现Window的type是TYPE_BASE_APPLICATION,也就是说,之前虽然该了type,但是没有生效,或者说,在我更改了type之后,系统又进行了更改,于是进入了下一步,撸源码。

4.何处设置了TYPE_BASE_APPLICATION
Activity Window从产生到WindowMnager#addView被调用,详细过程请自行查找,网上有较多的阐释。
我需要了解的核心大致如下:
在Activity#attach方法中产生PhoneWindow。
在ActivityThread#handleResumeActivity将DecorView添加到WindowManager。源码(API 19)如下:

if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (a.mVisibleFromClient) {a.mWindowAdded = true;wm.addView(decor, l);}// If the window has already been added, but during resume// we started another activity, then don't yet make the// window visible.}

好吧,找到了原因:add前,android“帮你”重设了type。


5.另有蹊径:WindowManager.LayoutParams privateFlags ???
撸Android 5.1(API 21)源码,发现它的PhoneWindowManager#interceptKeyBeforeDispatching方法home键事件处理逻辑与Android 4.4(API 19)有些许不同,如下:

if (keyCode == KeyEvent.KEYCODE_HOME) {... // If a system window has focus, then it doesn't make sense// right now to interact with applications.WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;if (attrs != null) {final int type = attrs.type;if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG|| (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {// the "app" is keyguard, so give it the keyreturn 0;}}...}

于是乎想,能不能在这个privateFlags上做文章。
WindowManager.LayoutParams中,privateFlags和PRIVATE_FLAG_KEYGUARD虽然是public的,但是是@hide注解的,所以访问不到,需要通过反射取值和修改,代码如下:

    public static void changeWindowPrivateFlags(Window window) {WindowManager.LayoutParams attrObj = window.getAttributes();Class<?> attrCls = attrObj.getClass();try {//拿PRIVATE_FLAG_KEYGUARD的值Field privateFlagConstField = attrCls.getField("PRIVATE_FLAG_KEYGUARD");privateFlagConstField.setAccessible(true);int privateFlagConst = privateFlagConstField.getInt(attrCls);//设置privateFlags为PRIVATE_FLAG_KEYGUARDField field = attrCls.getField("privateFlags");field.setAccessible(true);field.setInt(attrObj, privateFlagConst);} catch (Exception e) {e.printStackTrace();}}

在Activity onCreate中调用这个方法。好吧,还是无效。但奇怪的是,我在onKeyDown中打断点,发现privateFlags确实等于PRIVATE_FLAG_KEYGUARD。然后就想不通了,如果博友们有通了的,麻烦回复下,感谢!


至此,拦截home宣告失败,但明晰了一些原理,还是颇有收获的。
敢于怀疑,勇于探索。

Android关于Activity屏蔽/拦截Home键相关推荐

  1. android 发广播屏蔽home键,如何在Android App中屏蔽(拦截)Home按键及其他按键

    如何在Android App中屏蔽(拦截)Home按键及其他按键 (2013-09-08 13:29:11) 标签: 关键 按键 关键点 方法 安卓 it 编写一个Acitivity,如下所示: 关键 ...

  2. Android系统onKeyDown监控/拦截/监听/屏蔽返回键、菜单键和Home键

    我们可以在很多应用中都能看到按两次返回键退出 , 其实这个功能实现很容易, 下面就是实现的代码 , 把它放到你的程序中你的程序就能按两次返回键退出啦  , 这个功能是为了避免误点而把程序退出了 ,给你 ...

  3. android如何屏蔽掉home键

    在2.3版本以下重写下面方法就能重写home键 public void onAttachedToWindow() {       this.getWindow().setType(WindowMana ...

  4. HOME键窥探Android的Activity生命周期

    HOME键窥探Android的Activity生命周期 好久没有写技术博客了,前两篇博客写的都是一些自己的所见所闻和心里感受,今天说一说Android中的Activity的生命周期,此篇文章使用HOM ...

  5. android 退出功能,android中activity连按两次返回键退出功能

    直接写一个基类BaseActivity.java其它Activity都继承它就可以啦package com.main; import android.app.Activity; import andr ...

  6. Toast的另类应用及另类“拦截”Home键

    我们都知道Toast的几种用法,像什么居中啊,添加图片显示啊等等.不过这里我要说的是能够全屏显示和永远不会消失的另类Toast.全屏显示和之前大家了解的居中有点类似,只要修改setGravity(in ...

  7. 【Android】Activity生命周期(亲测)

    测试手机:Nexus 5   系统:4.4 一.测试 测试代码: 1 package com.example.androidalarm; 2 3 import android.app.Activity ...

  8. 006 Android之Activity

    文章目录 四大组件之Activity Activety概述 Activity的响应事件 Activity之间的数据传递 数据传递实例 Activity的生命周期 Activity声明周期总结 Acti ...

  9. Android的Activity生命周期模拟程序及解析

    当Activity处于Android应用中运行时,它的活动状态由Android以Activity栈的形式管理.当前活动的Activity位于栈顶.随着不同应用的运行,每个Activity都有可能从活动 ...

  10. Android-完美解决在Activity中触摸返回键onBackPressed不能触发问题

    场景:在一个只有WebView组件的Activity中如何正确处理页面的返回? 之前思路是覆写Activity的onBackPressed方法,因为用户触摸"返回键"会触发该方法: ...

最新文章

  1. 64位win10系统无法安装.Net framework3.5的解决方法
  2. 架构师之路 — API 经济 — 身份认证系统
  3. Java Review - HashMap HashSet 源码解读
  4. 前阿里巴巴产品专家明卿:当下做通用积分还是个好生意吗?
  5. java word分词器使用_word分词器使用(java)
  6. Three.js中引入dat.gui库实现界面组件控制动画速度变量
  7. String和Date、Timestamp之间的转换
  8. Java后台请求远程链接
  9. 理解Javascript_12_执行模型浅析
  10. 【OpenCV 例程200篇】60. 非线性滤波—联合双边滤波
  11. 【Hbase】HBase分布式安装
  12. 列出所有子集----------2013年1月3日
  13. HDFS读流程,写流程,放置策略
  14. 重定向ISA日志到SQL2000
  15. 【OpenCV】绘图与注释——绘制色差图
  16. 微软drive服务器,OneDrive:微软云存储服务
  17. 等保备案和通信网络单元定级备案的五大区别讲解
  18. Proxmox监视器
  19. vimdiff常用命令详解
  20. 初识html及工具的使用

热门文章

  1. IBM 2005-B16 SAN光纤交换机学习笔记
  2. 博科Brocade系列光纤交换机报价 程鹏宇 13829750520
  3. c++勾股定理解直三角形边长
  4. 机器人C++库(6)Robotics Library 例程三之正逆运动学计算
  5. php smart模板技术入门教程
  6. OXY OPENCART 商城自适应主题模板 ABC-0020-01
  7. iOS/苹果开发者账户添加测试设备UDID
  8. aptana手动配置python环境_Python学习1:使用Aptana构建Python开发环境
  9. 怎么设置计算机桌面一键关机,图文详解如何设置电脑定时开关机
  10. 【雅思大作文考官范文】——第十七篇: 'economic progress' essay