You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发考勤Android应用时,如何在应用运行时禁用悬浮应用?

考勤应用中检测/禁用悬浮应用方案

需求背景

开发考勤应用时,为防止用户通过WhatsApp等悬浮应用共享考勤代码,需要实现悬浮应用的检测或禁用功能。悬浮应用遮挡界面的示例如下:
悬浮窗口遮挡考勤应用界面

已尝试的方案

  • 在输入考勤代码的EditText上添加焦点变化监听器,试图通过焦点转移判断是否切换到其他应用,但监听器未生效,代码如下:
codeView.setOnFocusChangeListener((v, hasFocus) -> {
    if (!hasFocus) {
        checkCurrentRollNoAndRemoveAttendance();
    }
});
  • 尝试通过代码修复「屏幕叠加层检测」问题
  • 尝试配置android:filterTouchesWhenObscured属性
  • 尝试搜索Android平台检测/拦截悬浮应用的方案
  • 尝试解决点击按钮时EditText失去焦点的问题

可行解决方案

一、检测悬浮应用的存在

利用Android系统的WindowManager可以检测当前是否有其他应用的悬浮窗口覆盖在当前应用之上:

  1. 核心检测方法
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;
}
  1. 定时检测逻辑
    通过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);
}

二、限制界面交互,防止悬浮应用干扰

  1. 启用触摸过滤属性
    在布局文件的EditText中添加android:filterTouchesWhenObscured="true",当界面被悬浮窗口遮挡时,直接拒绝接收触摸事件:
<EditText
    android:id="@+id/codeView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:filterTouchesWhenObscured="true" />
  1. 监听窗口焦点变化
    通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 09:40:37