想在系统锁屏界面弹出Toast给用户提示,结果死活弹不出来,后来发现Toast其实已经弹出来了,只是被锁屏给挡住了。
原因:
Android的窗口的分层管理,即我们看到的屏幕显示只是z轴(z-ordered)最外面的,后面的其实是被挡住了(虽然看不见但它依然存在),故要想让Toast显示出来,其层级一定要在锁屏之上才行。
应用Window层级范围[1-99], 子Window的层级范围[1000-1999], 系统Window的层级范围[2000-2999]
实现代码:
Toast mToast = Toast.makeText(mContext, mContext.getString(com.android.internal.R.string.keyguardon_not_switch), Toast.LENGTH_SHORT);
mToast.getWindowParams().type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
mToast.getWindowParams().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mToast.getWindowParams().flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mToast.show();
主要参数:
/frameworks/base/core/java/android/view/WindowManager.java
/** 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
* {@link #FLAG_KEEP_SCREEN_ON} to turn screen on and display windows
* directly before showing the key guard window. Can be used with
* {@link #FLAG_DISMISS_KEYGUARD} to automatically fully dismisss
* non-secure keyguards. This flag only applies to the top-most
* full-screen window.
*/
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
/** In a multiuser system if this flag is set and the owner is a system process then this
* window will appear on all user screens. This overrides the default behavior of window
* types that normally only appear on the owning user's screen. Refer to each window type
* to determine its default behavior.
* * {@hide} */
public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
参考资料
1.锁屏界面无法无法显示Toast(介绍了非系统应用的实现)
https://blog.csdn.net/u013398960/article/details/73194812
2.延伸阅读
2.1 Android窗口管理分析(3):窗口分组及Z-order的确定
https://blog.csdn.net/happylishang/article/details/77893723
2.2 源码
frameworks/base/core/java/android/view/WindowManager.java
3.疑问
3.1 https://github.com/weidongshan/APP_0010_SurfaceTest/blob/master/SurfaceTest.cpp#L46
window的z-ordered显然要和surface的layer对应,这中间怎么处理的?
surfaceControl->setLayer(100000);