Android O - FLAG_SHOW_WHEN_LOCKED 已弃用

Android O - FLAG_SHOW_WHEN_LOCKED is deprecated

我的申请对象是 Android O。 在我的应用程序中,我有一个作业服务显示 window 超过所有其他应用程序,因此当它触发时它需要显示此 window 即使屏幕已关闭并解锁并打开它。 我在之前的 Android 版本中实现了这种行为,但在 Android O 中它并没有像我预期的那样工作。

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

所以当屏幕打开时它工作正常,但是当屏幕关闭时我注意到它没有打开屏幕,当我打开屏幕时我看到 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);
}

备注:

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

FLAG_TURN_SCREEN_ON

int FLAG_TURN_SCREEN_ON This constant was deprecated in API level 27. Use turnScreenOn or setTurnScreenOn(boolean) instead to prevent an unintentional double life-cycle event.

Window flag: when set as a window is being added or made visible, once the window has been shown then the system will poke the power manager's user activity (as if the user had woken up the device) to turn the screen on.

FLAG_SHOW_WHEN_LOCKED

int FLAG_SHOW_WHEN_LOCKED This constant was deprecated in API level 27. Use showWhenLocked or setShowWhenLocked(boolean) instead to prevent an unintentional double life-cycle event.

Window flag: special flag to let windows be shown when the screen is locked. This will let application windows take precedence over key guard or any other lock screens. Can be used with FLAG_KEEP_SCREEN_ON to turn screen on and display windows directly before showing the key guard window. Can be used with FLAG_DISMISS_KEYGUARD to automatically fully dismisss non-secure keyguards. This flag only applies to the top-most full-screen window.

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

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

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

时屏幕开启

现在替换标志的方法:FLAG_SHOW_WHEN_LOCKED FLAG_TURN_SCREEN_ON 对活动可见,对服务或 WindowManager 不可见,并且将上下文转换为 Activity 不是一个好方法想法,不会帮助你:)

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

在 activity - 在 onCreate 方法中,我正在调用以下方法:

setShowWhenLocked(true) 
setTurnScreenOn(true)

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

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

我这样做的原因:

我正在使用语音识别器.. 当我在 activity 中对其进行编码时,没有任何效果。我的意思是当屏幕被模式锁定时,activity 进入暂停状态,我无法得到结果。所以模式解雇了我的 activity..

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

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

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)
    }
}

你经历过吗

setShowWhenLocked(true)
setTurnScreenOn(true)

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

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