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

Android:如何在设置应用及锁屏上层显示Overlay View

技术方案:让无障碍服务的Overlay View在设置应用及锁屏界面持续显示

一、修正WindowManager布局参数配置

必须使用TYPE_ACCESSIBILITY_OVERLAY(Android 8.0+),这是无障碍服务专属的窗口类型,优先级高于普通悬浮窗,能突破系统对设置应用、锁屏界面的显示限制。核心参数配置如下:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
        WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY :
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
        WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON,
    PixelFormat.TRANSLUCENT
);

重点注意:

  • 必须添加FLAG_SHOW_WHEN_LOCKED和FLAG_ALLOW_LOCK_WHILE_SCREEN_ON,确保锁屏时不隐藏
  • 绝对不能加FLAG_HIDE_WHEN_LOCKED这类会导致锁屏隐藏的flag
  • TYPE_SYSTEM_ALERT是兼容Android 7.1及以下版本的替代类型

二、通过无障碍事件回调主动维护Overlay状态

重写无障碍服务的onAccessibilityEvent方法,监听应用切换和锁屏状态变化,强制触发Overlay的显示/刷新,避免系统自动隐藏:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    // 监听应用窗口切换事件
    if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
        String packageName = event.getPackageName().toString();
        // 切换到设置应用时,强制刷新Overlay(移除后重新添加或调用invalidate)
        if ("com.android.settings".equals(packageName)) {
            refreshOverlay();
        }
    }
    // 监听屏幕锁屏事件
    else if (eventType == AccessibilityEvent.TYPE_SCREEN_STATE_CHANGED) {
        if (!event.isEnabled()) {
            // 锁屏时确保Overlay已添加到窗口
            ensureOverlayVisible();
        }
    }
}

private void refreshOverlay() {
    if (mOverlayView != null) {
        mWindowManager.removeView(mOverlayView);
    }
    mWindowManager.addView(mOverlayView, mLayoutParams);
}

private void ensureOverlayVisible() {
    if (mOverlayView != null && mOverlayView.getParent() == null) {
        mWindowManager.addView(mOverlayView, mLayoutParams);
    }
}

三、检查无障碍服务的配置与权限

  1. 确保服务在AndroidManifest.xml中正确注册,且meta-data配置足够的监听权限:
<service
    android:name=".YourAccessibilityServiceImpl"
    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>
  1. 对应的accessibility_config.xml需要开启必要的事件监听:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged|typeScreenStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_desc" />
  1. 无需申请普通悬浮窗权限SYSTEM_ALERT_WINDOW,TYPE_ACCESSIBILITY_OVERLAY不需要该权限,反而可能引发冲突。

四、额外防护:定时检查Overlay状态

用Handler实现定时检查,防止Overlay被系统意外回收:

private Handler mCheckHandler = new Handler();
private Runnable mCheckRunnable = new Runnable() {
    @Override
    public void run() {
        ensureOverlayVisible();
        mCheckHandler.postDelayed(this, 30000); // 每30秒检查一次
    }
};

// 在服务启动时启动检查
@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    mCheckHandler.post(mCheckRunnable);
}

// 服务销毁时停止检查
@Override
public void onDestroy() {
    super.onDestroy();
    mCheckHandler.removeCallbacks(mCheckRunnable);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:52:44