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

Android O中FLAG_SHOW_WHEN_LOCKED废弃后,如何实现亮屏并显示悬浮窗

Android O (API 27) 替代 FLAG_TURN_SCREEN_ON 和 FLAG_SHOW_WHEN_LOCKED 的方案

针对你在Android O上面临的悬浮窗亮屏问题,我来给你梳理下官方推荐的替代方案,以及如何修改你的代码:


1. 替代 FLAG_TURN_SCREEN_ON:使用 PowerManager.wakeUp()

从API 23开始,官方就推荐用PowerManager.wakeUp()来直接唤醒屏幕,而不是依赖Window的FLAG。这个方法需要在清单中声明WAKE_LOCK权限:

<uses-permission android:name="android.permission.WAKE_LOCK"/>

调用方式很简单,获取PowerManager实例后直接调用:

PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager != null) {
    // 传入当前时间戳,唤醒屏幕
    powerManager.wakeUp(System.currentTimeMillis());
}

2. 替代 FLAG_SHOW_WHEN_LOCKED 和 FLAG_TURN_SCREEN_ON:View级别的Setter方法

从API 27开始,Android提供了View的两个方法来替代对应的FLAG:

  • setShowWhenLocked(true):让View在锁屏状态下显示
  • setTurnScreenOn(true):触发屏幕点亮(配合wakeUp效果更稳定)

这两个方法需要在你添加View到WindowManager之前调用。


修改后的完整代码示例

结合你的现有代码,调整后如下:

private void showView() {
    // 1. 唤醒屏幕(替代FLAG_TURN_SCREEN_ON)
    PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    if (powerManager != null && !powerManager.isInteractive()) { // 仅在屏幕未点亮时触发唤醒
        powerManager.wakeUp(System.currentTimeMillis());
    }

    // 2. 获取WindowManager并创建布局参数
    windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
    final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
            0,
            0,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            // 移除废弃的FLAG,保留其他必要的
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
            PixelFormat.RGBA_8888);

    // 3. 构建View并设置锁屏显示和亮屏属性
    RelativeLayout layout = buildView();
    // API 27+ 替代FLAG_SHOW_WHEN_LOCKED和FLAG_TURN_SCREEN_ON
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        layout.setShowWhenLocked(true);
        layout.setTurnScreenOn(true);
    }

    // 4. 添加并更新View
    windowManager.addView(layout, layoutParams);
    windowManager.updateViewLayout(layout, layoutParams);

    // 处理WakeLock(保持屏幕常亮)
    if (!wakeLockAcquired) {
        wakeLock.acquire();
        wakeLockAcquired = true; // 修正了你原代码中的变量名拼写错误
    }
}

关键说明

  • 为什么之前的代码不生效?因为Android O开始,FLAG_TURN_SCREEN_ON和FLAG_SHOW_WHEN_LOCKED这两个FLAG对TYPE_APPLICATION_OVERLAY类型的窗口不再生效,必须使用View级别的Setter方法。
  • 权限检查:确保你不仅申请了SYSTEM_ALERT_WINDOW,还添加了WAKE_LOCK权限,并且在运行时已经获取了悬浮窗权限(Android 6.0+需要用户手动开启)。
  • 变量名修正:你原代码里wakeLockAquired拼写错误,示例中已经修正为wakeLockAcquired。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:28:59