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

Android后台检测是否有窗口设置LayoutParams.FLAG_SECURE的方法

检测前台窗口是否设置了FLAG_SECURE的正确姿势

嘿,你之前的代码踩了个小坑——你用Display.FLAG_SECURE来判断窗口的安全标志,这完全不对!这个标志是用来标记整个显示设备是否需要防截屏/录屏的全局设置,和单个窗口的WindowManager.LayoutParams.FLAG_SECURE半毛钱关系都没有,所以它才会一直返回true。

要准确检测某个窗口是否设置了FLAG_SECURE,得针对单个窗口的LayoutParams来判断,但这里要注意Android的权限和版本限制,下面给你两种可行的方案:

方案1:用AccessibilityService(后台检测首选)

AccessibilityService是目前后台检测其他窗口状态最可靠的方式,不过需要用户手动给你的应用开启辅助功能权限。

第一步:配置AccessibilityService

先在AndroidManifest.xml里注册服务:

<service
    android:name=".MySecureWindowCheckerService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_config" />
</service>

然后在res/xml/accessibility_config.xml里写配置:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_desc"
    android:accessibilityFlags="flagIncludeNotImportantViews" />

(记得在strings.xml里加accessibility_desc,说明你的服务用途,比如“检测窗口是否设置了安全保护标志”)

第二步:实现检测逻辑

写一个继承AccessibilityService的类,监听窗口切换事件,拿到当前窗口的LayoutParams:

public class MySecureWindowCheckerService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 只处理窗口切换事件
        if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            return;
        }

        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if (rootNode == null) {
            return;
        }

        // 从窗口节点的 extras 里取出LayoutParams
        WindowManager.LayoutParams windowParams = 
            (WindowManager.LayoutParams) rootNode.getExtras().get("android.view.WindowManager.LayoutParams");
        
        if (windowParams != null) {
            boolean isSecure = (windowParams.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0;
            Log.d("WindowSecureCheck", "当前窗口是否设置FLAG_SECURE: " + isSecure);
            // 这里可以把结果传递给你的后台逻辑
        }

        rootNode.recycle(); // 别忘了回收节点,避免内存泄漏
    }

    @Override
    public void onInterrupt() {
        // 服务被中断时的处理,比如打个log
        Log.d("WindowSecureCheck", "辅助服务被中断");
    }
}

方案2:用UsageStatsManager(局限性大,仅低版本可用)

如果你只是想知道前台应用的情况,可以先通过UsageStatsManager拿到前台包名,但注意:Android 10+后台根本拿不到其他应用的窗口LayoutParams,这个方案只能作为低版本的补充。

第一步:申请权限

在Manifest里加权限:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions" />

然后引导用户到设置页面授权:

private void requestUsageStatsPermission(Context context) {
    Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
    context.startActivity(intent);
}

第二步:获取前台包名(但无法直接检测窗口FLAG_SECURE)

public String getForegroundPackage(Context context) {
    UsageStatsManager statsManager = 
        (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    long now = System.currentTimeMillis();
    // 查询最近1小时的应用使用记录
    List<UsageStats> statsList = statsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_HOURLY, now - 3600000, now);
    
    if (statsList == null || statsList.isEmpty()) {
        return null;
    }

    String foregroundPkg = null;
    long lastActiveTime = 0;
    for (UsageStats stats : statsList) {
        if (stats.getLastTimeUsed() > lastActiveTime) {
            lastActiveTime = stats.getLastTimeUsed();
            foregroundPkg = stats.getPackageName();
        }
    }
    return foregroundPkg;
}

但还是那句话,拿到包名也没用,高版本后台根本拿不到别人的窗口参数。

重要提醒

  • Android 10(API 29)及以上:后台应用想获取其他应用的窗口信息,几乎只有AccessibilityService这一条路,而且必须用户手动授权辅助功能。
  • 系统应用除外:如果你的应用是系统级别的,那可以用更直接的方法,但一般第三方应用没这个权限。

内容的提问来源于stack exchange,提问作者CamHart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:16:54