Android O - FLAG_SHOW_WHEN_LOCKED已弃用

时间:2018-01-16 08:53:04

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

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

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

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

所以我的问题是,因为Android API 27中不推荐使用标记FLAG_TURN_SCREEN_ONFLAG_SHOW_WHEN_LOCKED,这样做的替代方法是什么?

这是我目前的代码:

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。

5 个答案:

答案 0 :(得分:7)

因此根据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 :(得分:7)

如果attr turnScreenOn为true,则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)
    }
}

答案 2 :(得分:6)

好的,所以我设法通过一些解决方法和@Umair答案的帮助来解决它。

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

现在替换Flags的方法:FLAG_SHOW_WHEN_LOCKED FLAG_TURN_SCREEN_ON对于活动而不是对于服务或WindowManager是可见的,并且将上下文转换为Activity不是一个好主意,并且不会帮助您:)

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

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

setShowWhenLocked(true) 
setTurnScreenOn(true)

当视图被破坏时,活动也会在广播接收器的帮助下被破坏:) 所以现在屏幕已打开,视图高于所有其他应用程序。

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

我这样做的原因是:

我使用语音识别器......当我在活动中对其进行编码时,事情并没有奏效。我的意思是当屏幕被模式锁定时,活动进入暂停状态,我无法获得结果。所以模式驳回了我的活动..

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

答案 3 :(得分:1)

您是否经历过

setShowWhenLocked(true)
setTurnScreenOn(true)

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

答案 4 :(得分:0)

如Dmitry Ognyov上面所述-除了这些: setShowWhenLocked(true); setTurnScreenOn(true); 您也需要解雇键盘锁keyguardManager.requestDismissKeyguard(...