【问题标题】:Android O - FLAG_SHOW_WHEN_LOCKED is deprecatedAndroid O - FLAG_SHOW_WHEN_LOCKED 已弃用
【发布时间】:2018-01-16 08:53:03
【问题描述】:

我将我的应用程序定位到 Android O。 在我的应用程序中,我有一个工作服务,它在所有其他应用程序上显示一个窗口,所以当它触发时,即使屏幕关闭和解锁并打开它,它也需要显示这个窗口。 我已经在之前的 Android 版本中实现了这种行为,但在 Android O 中它并没有像我预期的那样工作。

我读到我需要使用标志 TYPE_APPLICATION_OVERLAY 并在清单文件中添加了权限 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

所以当屏幕打开时它工作正常,但是当屏幕关闭时我注意到它没有打开屏幕,当我打开屏幕时我看到窗口是在其他窗口之上创建的应用程序。

所以我的问题是,由于标志 FLAG_TURN_SCREEN_ONFLAG_SHOW_WHEN_LOCKED 在 Android API 27 中已被弃用,有哪些替代方法?

这是我当前的代码:

private void showView()
{
    if (!wakeLockAcquired)
    {
        wakeLock.acquire();
        wakeLockAquired = true;
    }

    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
            ,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ,
            PixelFormat.RGBA_8888);

    RelativeLayout layout = buildView();
    windowManager.addView(layout, layoutParams);
    windowManager.updateViewLayout(layout, layoutParams);
}

注意事项:

  • buildView 是一个返回 relativeLayout 的函数,在这个函数中我动态添加内容(TextView、ImageView 等...)。
  • wakeLockAcquired 是一个布尔成员,当视图被销毁时它设置为 false。

【问题讨论】:

    标签: android android-windowmanager android-8.0-oreo


    【解决方案1】:

    如果 attr turnScreenOn 为真,KeyguardManager 打开屏幕,因此方法顺序和调用 requestDismissKeyguard 是必要的。我将此代码用于活动,希望对您有所帮助:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
            val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            keyguardManager.requestDismissKeyguard(this, null)
        } else {
            this.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
        }
    }
    

    【讨论】:

    • 小心,WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 在 API 26 而不是 27 中被弃用。
    • 什么是窗口?在哪个班?
    • 这是 Activity 实例
    • 对我来说 requestDismissKeyguard 仍然保留 PIN 输入键盘。
    • 同上评论,这不适用于 PIN 锁定屏幕(在 Android 11 上测试)
    【解决方案2】:

    好的,所以我设法通过一些解决方法和@Umair 的回答解决了这个问题。

    正如我所说,我正在显示一个使用 WindowManager 在后台服务中创建的视图,并使用我在上面的问题中添加的代码,该视图显示在所有其他应用程序之上,但没有打开屏幕当 Android 版本为 Android 8 时。

    现在替换标志的方法:FLAG_SHOW_WHEN_LOCKEDFLAG_TURN_SCREEN_ON 对活动可见,但对服务或 WindowManager 不可见,并且将上下文转换为 Activity 不是一个好主意,对您没有帮助:)

    所以我现在所做的(临时解决方案)是创建一个透明活动,当我从后台服务调用showView() 方法时,我也在启动透明活动。

    在活动中 - 在 onCreate 方法中,我正在调用方法:

    setShowWhenLocked(true) 
    setTurnScreenOn(true)
    

    当视图被销毁时,活动也会在广播接收器的帮助下被销毁:) 因此屏幕现在已打开,并且视图位于所有其他应用程序之上。

    我知道您可以告诉我,我可以将服务中的代码移动到新活动中。

    我这样做的原因:

    我正在使用语音识别器..当我在活动中对其进行编码时,一切都不起作用。我的意思是当屏幕被模式锁定时,活动进入暂停状态,我无法得到结果。所以模式取消了我的活动..

    所以我决定使用窗口管理器创建一个视图,直到现在它都运行良好 - 当 Google(Android 团队)决定弃用这些标志时。 所以这是我现在的解决方案..我希望有人能找到更好的解决方案。

    【讨论】:

      【解决方案3】:

      因此,根据 android 文档,这些方法已被弃用,因此您需要改用 showWhenLocked or setShowWhenLocked(boolean)

      FLAG_TURN_SCREEN_ON
      

      int FLAG_TURN_SCREEN_ON 此常量在 API 级别 27 中已弃用。 改用 turnScreenOn 或 setTurnScreenOn(boolean) 来防止 无意的双生命周期事件。

      窗口标志:当设置为窗口被添加或可见时,一次 窗口已显示然后系统将戳电源 经理的用户活动(就好像用户已经唤醒了设备) 打开屏幕。

      还有FLAG_SHOW_WHEN_LOCKED

      int FLAG_SHOW_WHEN_LOCKED 此常量在 API 级别 27 中已弃用。 请改用 showWhenLocked 或 setShowWhenLocked(boolean) 来防止意外的双生命周期事件。

      窗口标志:特殊标志,让窗口在屏幕显示时显示 锁定。这将使应用程序窗口优先于键 守卫或任何其他锁屏。可以与 FLAG_KEEP_SCREEN_ON 一起使用 在显示键之前直接打开屏幕并显示窗口 防护窗。可以与 FLAG_DISMISS_KEYGUARD 一起使用以自动 完全消除不安全的键盘保护。此标志仅适用于 最顶部的全屏窗口。

      因此,根据文档,弃用这些方法的原因是为了避免 an unintentional double life-cycle event. 您可以在此处阅读有关它们的更多信息。 https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html

      【讨论】:

      • 谢谢我也读过它。但似乎这些方法仅在活动中可见。当您在后台服务中创建视图时,我正在寻找解决方案。+1你的答案:)
      • FLAG_TURN_SCREEN_ON 也已弃用
      • @Rasel 如果您阅读了它在 API 27 中已弃用的详细信息 :)
      • 有没有人知道如何在后台服务@Elior 中使用这个服务
      【解决方案4】:

      你有这种经历吗

      setShowWhenLocked(true)
      setTurnScreenOn(true)
      

      在 Android 9 中不再开启屏幕?还是只是我的情况?

      【讨论】:

      • @Elior 我不需要使用您的解决方法,因为我想打开活动。我的问题是它曾经可以在 Android 8 上运行,但现在在 Android 9 上停止了。是我的情况还是你的情况相同?
      • 抱歉,响应延迟,实际上我没有在 Android 9 上尝试过。您要打开屏幕并显示活动吗?您的设备上是否设置了任何键盘保护?比如密码或图案?
      【解决方案5】:

      正如 Dmitry Ognyov 在上面发布的那样 - 除了这些: setShowWhenLocked(true); setTurnScreenOn(true); 你也需要解散键盘锁keyguardManager.requestDismissKeyguard(...

      【讨论】:

      • 这对于 Android 11 来说似乎不够
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-25
      • 2021-08-31
      • 2015-09-18
      • 2018-02-11
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多