Android 12+ setHideOverlayWindows用法及防点击劫持失效问题求助
解决Android 12+点击劫持防护中
setHideOverlayWindows无效的问题 一、setHideOverlayWindows的正确使用方式
权限声明
必须在AndroidManifest.xml中声明对应权限,该权限为正常权限,无需动态申请:<uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />调用时机
需要在窗口初始化完成后调用,比如Activity.onCreate()中setContentView()之后,或onStart()/onResume()方法内。调用过早(如窗口未创建时)会导致设置不生效。作用范围
该方法仅对当前调用的窗口生效,所有需要防护的敏感页面(如支付、登录页)都需单独设置,并非全局配置。正确代码示例
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rooted_check); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { getWindow().setHideOverlayWindows(true); } }
二、排查无效原因
- 调用时机错误:若在
setContentView()之前调用,系统无法正确应用窗口配置。 - 未覆盖所有敏感页面:仅在部分页面设置,其他风险页面仍会暴露。
- 窗口类型限制:特殊窗口类型(如悬浮窗、系统级窗口)不受该方法影响,确保目标页面为普通应用窗口。
三、验证功能生效的方法
手动测试
- 编写一个简单的悬浮窗测试应用,或使用具备悬浮窗功能的工具。
- 打开已设置
setHideOverlayWindows(true)的页面,启动悬浮窗覆盖其上。 - 正常生效时,系统会自动隐藏覆盖在目标窗口上的第三方悬浮层,确保目标窗口为最上层可交互界面。
代码层面验证
通过监听窗口焦点变化,结合窗口属性判断设置状态:getWindow().getDecorView().setOnWindowFocusChangeListener((v, hasFocus) -> { if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { WindowManager.LayoutParams params = getWindow().getAttributes(); boolean isOverlayHidden = params.hideOverlayWindows; Log.d("TapjackingCheck", "Overlay hide status: " + isOverlayHidden); } });系统日志验证
过滤系统日志中HIDE_OVERLAY_WINDOWS关键词,查看系统是否成功应用该配置的相关记录。
四、Android 12+点击劫持防护补充方案
除setHideOverlayWindows外,可结合以下方案强化防护:
- 保留原有窗口标志检测逻辑,在检测到覆盖层时禁用敏感控件:
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int flags = getWindow().getDecorView().getWindowSystemUiVisibility(); boolean isObscured = false; if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { isObscured = (flags & View.FLAG_WINDOW_IS_OBSCURED) != 0; } else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { isObscured = ((flags & View.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0) || ((flags & View.FLAG_WINDOW_IS_OBSCURED) != 0); } else { isObscured = !getWindow().getAttributes().hideOverlayWindows; } // 禁用敏感按钮或输入框 findViewById(R.id.sensitive_input).setEnabled(!isObscured); } } - 使用
View.setFilterTouchesWhenObscured(true),让控件在被覆盖时拒绝接收触摸事件,兼容Android 4.0及以上版本。
内容的提问来源于stack exchange,提问作者Vijayadhas Chandrasekaran
相关产品推荐
相关产品推荐

