场景
手机管理软件的一部分:在某个时候需要输入自定义密码才能使用手机。这时候要禁用 Home 键,可以采取策略
AccessibilityService的onKeyEvent屏蔽 Home
一个附件在WindowManager上的浮层
然后下一步是屏蔽用户用手势下拉系统栏(StatusBar)
目标
在限制模式下,禁止用户下拉显示状态栏从而进行其他操作
决策
全局窗口 - 失败
Activity全屏,这样确实可以遮挡住系统栏,但是却无法阻止下拉手势唤出它
另外,5.0的沉浸模式,感觉照样白扯,无法屏蔽
AccessibilityService方案 - 失败
首先,利用 AccessibilityService 的 onGesture 函数,这个要求手机进入 Touch Exploration ModeFLAG_REQUEST_TOUCH_EXPLORATION_MODE
经测试,这个确实可以截获各种手势,但是进入 Touch Exploration Mode onGesture 返回值没什么作用,无论返回什么结果,都会是一种现象:手势全部被截获,虽然无法拉出系统栏了,但是 完全触摸模式下滑动桌面,点击都没效果了。
后来逐渐解决其他问题
锁屏界面也是触摸模式 - 检测进入锁屏后关闭触摸模式
界面无法点击 - 检测 TYPE_VIEW_HOVER_ENTER 之后模拟点击
输入法不能用(也是点击相关) - 没方案
知道我看到了一句话 when FLAG_REQUEST_TOUCH_EXPLORATION_MODE is being used there is a need to swipe with 2 fingers or double click and swipe 来自 AccessibilityService with FLAG_REQUEST_TOUCH_EXPLORATION_MODE cause device to stuck !!!,才开始后悔没啥没有早看文档 - Touch Exploration Mode 模式下,双击果然是单击,两个指头滑动果然他妈的能是手势有效果,自然也就可以滑下来系统栏了
后来检查一个 AccessibilityService 的 onKeyEvent 函数,大喜,然后大悲,这个可以截获键盘操作,但是对触摸操作无能为力
再后来,放弃了
悬浮窗口解决方案
方法:
public static int getNotifyBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
使用:
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = getNotifyBarHeight(this);
localLayoutParams.format = PixelFormat.TRANSPARENT;
View view = new View(this);
manager.addView(view, localLayoutParams);
注意加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
在有些已经被改的烂七八糟的系统,例如MIUI上,需要安装APP后自己开启允许悬浮窗口选项
然后,世界清净了
localLayoutParams.flags设置的三个参数奥妙无穷,可以自己体会一下
另外,还有一种笨方案
还是利用 AccessibilityService, 检测到系统栏滑下来之后 赶紧关闭它, 例如模拟后退键,模拟Home键,但这个一个是会有系统栏闪动,一个是隐藏系统栏的方法比较难统一,所以也就放弃了
其他
参考还提供了一种很炫的方案
Disable:
service call activity 42 s16 com.android.systemui
Enable:
am startservice -n com.android.systemui/.SystemUIService
经过测试,4.*的机器上可用,又说5.0上不能用的,还是有即使4.0上也会导致桌面背景消失等奇怪的现象
参考
http://stackoverflow.com/questions/21371802/permanently-hide-android-status-bar