在我的应用程序中,我有一个比所有其他应用程序都要显示窗口的作业服务,所以当它触发时,它需要显示这个窗口,即使屏幕被关闭&解锁并打开它。在以前的Android版本中,我已经实现了这种行为,但在Android中,它并不像我预期的那样工作。
我读到需要使用标志TYPE_APPLICATION_OVERLAY
,并在清单文件中添加权限<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
。
因此,当屏幕打开时,它可以正常工作,但当屏幕关闭时,我注意到它没有打开屏幕,当我打开屏幕时,我看到窗口是在其他应用程序之上创建的。
因此,我的问题是,既然在Android 27中反对使用FLAG_TURN_SCREEN_ON
和FLAG_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);
}
备注:
发布于 2018-01-16 04:12:24
好的,我设法解决了这个问题,找到了一些解决办法,并得到了@Umair的帮助。
正如我说过的,我正在显示一个使用WindowManager在后台服务中创建的视图,在上面添加的代码中,该视图显示在所有其他应用程序之上,但当Android版本为Android8时,该视图不会打开屏幕。
现在取代Flags:FLAG_SHOW_WHEN_LOCKED
FLAG_TURN_SCREEN_ON
的方法对于活动是可见的,而不是对于服务或WindowManager,并且将上下文转换为Activity不是一个好主意,也无助于您:)
所以我现在所做的(临时解决方案)是创建一个透明的活动,当我从后台服务调用showView()
方法时,我也开始透明的活动。
在活动--在onCreate方法中,我调用以下方法:
setShowWhenLocked(true)
setTurnScreenOn(true)
当视图被销毁时,活动也将在广播接收器的帮助下被销毁:)因此,屏幕现在被打开,视图高于所有其他应用程序。
我知道,您可以告诉我,我可以将服务中的代码移动到新的活动中。
我这么做的原因是:
我在用语音识别器..。当我在活动中对它进行编码时,事情就不起作用了。我的意思是,当屏幕被模式锁定时,活动会进入暂停状态,而我无法得到结果。所以这个模式否定了我的活动。
因此,我决定使用窗口管理器创建一个视图,直到现在,它一直运行良好--那时Google (Android团队)决定放弃这些标志。所以这是我现在的解决方案。我希望有人能为这个问题找到更好的解决办法。
发布于 2018-05-03 08:22:20
如果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)
}
}
发布于 2018-01-16 01:00:14
因此,根据android文档,这些方法是不推荐的,因此您需要使用showWhenLocked or setShowWhenLocked(boolean)
。
FLAG_TURN_SCREEN_ON
int FLAG_TURN_SCREEN_ON 这个常量在API级别27中被废弃。使用turnScreenOn或setTurnScreenOn(布尔值)来防止意外的双重生命周期事件. 窗口标志:当设置为窗口被添加或使之可见时,一旦窗口被显示,系统就会戳开电源管理器的用户活动(就像用户唤醒了设备一样)来打开屏幕。
和FLAG_SHOW_WHEN_LOCKED
int FLAG_SHOW_WHEN_LOCKED 这个常量在API级别27中被废弃。使用showWhenLocked或setShowWhenLocked(布尔值)来防止意外的双重生命周期事件. 窗口标志:在屏幕锁定时让窗口显示的特殊标志。这将使应用程序窗口优先于密钥保护或任何其他锁定屏幕。可以与FLAG_KEEP_SCREEN_ON一起使用,在显示键保护窗口之前直接打开屏幕并显示窗口。可与FLAG_DISMISS_KEYGUARD一起使用,以自动完全解除非安全的密钥保护。此标志仅适用于最顶部的全屏窗口.
因此,根据文档,反对这些方法的原因是为了避免an unintentional double life-cycle event.
,您可以在这里更多地了解它们。https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html
https://stackoverflow.com/questions/48277302
复制