开发考勤Android应用时,如何在应用运行时禁用悬浮应用?
考勤应用中检测/禁用悬浮应用方案
需求背景
开发考勤应用时,为防止用户通过WhatsApp等悬浮应用共享考勤代码,需要实现悬浮应用的检测或禁用功能。悬浮应用遮挡界面的示例如下:
已尝试的方案
- 在输入考勤代码的
EditText上添加焦点变化监听器,试图通过焦点转移判断是否切换到其他应用,但监听器未生效,代码如下:
codeView.setOnFocusChangeListener((v, hasFocus) -> { if (!hasFocus) { checkCurrentRollNoAndRemoveAttendance(); } });
- 尝试通过代码修复「屏幕叠加层检测」问题
- 尝试配置
android:filterTouchesWhenObscured属性 - 尝试搜索Android平台检测/拦截悬浮应用的方案
- 尝试解决点击按钮时EditText失去焦点的问题
可行解决方案
一、检测悬浮应用的存在
利用Android系统的WindowManager可以检测当前是否有其他应用的悬浮窗口覆盖在当前应用之上:
- 核心检测方法
private boolean hasOverlayWindow() { WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); if (windowManager == null) return false; List<WindowManager.LayoutParams> windowParamsList = windowManager.getAppTokens(); for (WindowManager.LayoutParams params : windowParamsList) { // 适配Android 8.0及以上的悬浮窗口类型 if (params.type == WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY) { return true; } // 兼容Android 8.0以下的旧悬浮窗口类型 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && (params.type == WindowManager.LayoutParams.TYPE_SYSTEM_ALERT || params.type == WindowManager.LayoutParams.TYPE_PHONE)) { return true; } } return false; }
- 定时检测逻辑
通过Handler定时执行检测,一旦发现悬浮应用就触发拦截逻辑:
private Handler overlayCheckHandler = new Handler(); private Runnable overlayCheckRunnable = new Runnable() { @Override public void run() { if (hasOverlayWindow()) { // 检测到悬浮应用,执行清理或警告操作 codeView.setText(""); Toast.makeText(MainActivity.this, "禁止使用悬浮应用,请关闭后重试", Toast.LENGTH_SHORT).show(); } // 每1秒检测一次,可根据需求调整间隔 overlayCheckHandler.postDelayed(this, 1000); } }; // 在Activity恢复前台时启动检测 @Override protected void onResume() { super.onResume(); overlayCheckHandler.post(overlayCheckRunnable); } // 在Activity退后台时停止检测,避免资源浪费 @Override protected void onPause() { super.onPause(); overlayCheckHandler.removeCallbacks(overlayCheckRunnable); }
二、限制界面交互,防止悬浮应用干扰
- 启用触摸过滤属性
在布局文件的EditText中添加android:filterTouchesWhenObscured="true",当界面被悬浮窗口遮挡时,直接拒绝接收触摸事件:
<EditText android:id="@+id/codeView" android:layout_width="match_parent" android:layout_height="wrap_content" android:filterTouchesWhenObscured="true" />
- 监听窗口焦点变化
通过Activity的窗口焦点监听,确保只有当前应用处于前台时才能进行输入操作:
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!hasFocus) { // 应用失去窗口焦点,清除输入内容并提示 codeView.setText(""); Toast.makeText(this, "请回到考勤应用操作", Toast.LENGTH_SHORT).show(); } }
三、必要权限配置
在AndroidManifest.xml中添加以下权限,确保检测逻辑正常运行:
<!-- Android 6.0及以上需要的悬浮窗口权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 获取任务信息的权限,用于窗口检测 --> <uses-permission android:name="android.permission.GET_TASKS" />
内容的提问来源于stack exchange,提问作者Suyog
相关产品推荐
相关产品推荐

