Windowmanager悬浮窗的 WindowManager.LayoutParams.type 属性属性研究

刚开始接触悬浮窗,看到网上有很多关于各个type 的介绍,但是没有具体说明它们之间的z轴顺序,所以特意做了调查。
一、含义:
首先先贴上各个type 的意义

  应用程序窗口。
  public static final int FIRST_APPLICATION_WINDOW = 1;    

  所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。     
  public static final int TYPE_BASE_APPLICATION   =1;

  普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
  public static final int TYPE_APPLICATION       = 2;

   用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。
  它用于让系统显示些信息,直到应用程序可以开启自己的窗口。   
  public static final int TYPE_APPLICATION_STARTING = 3; 

  应用程序窗口结束。
  public static final int LAST_APPLICATION_WINDOW = 99;

  子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。
  public static final int FIRST_SUB_WINDOW       = 1000;

  面板窗口,显示于宿主窗口上层。
  public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;

  媒体窗口,例如视频。显示于宿主窗口下层。
  public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;

  应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)
  public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;

  对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。
  public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;

  媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)
  public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;

  子窗口结束。( End of types of sub-windows )
  public static final int LAST_SUB_WINDOW        = 1999;

  系统窗口。非应用程序创建。
  public static final int FIRST_SYSTEM_WINDOW    = 2000;

  状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。
  public static final int TYPE_STATUS_BAR        =  FIRST_SYSTEM_WINDOW;

  搜索栏。只能有一个搜索栏;它位于屏幕上方。
  public static final int TYPE_SEARCH_BAR        = FIRST_SYSTEM_WINDOW+1;

  电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
  public static final int TYPE_PHONE            = FIRST_SYSTEM_WINDOW+2;

  系统提示。它总是出现在应用程序窗口之上。
  public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;

  锁屏窗口。
  public static final int TYPE_KEYGUARD          = FIRST_SYSTEM_WINDOW +4;

  信息窗口。用于显示toast。
  public static final int TYPE_TOAST            = FIRST_SYSTEM_WINDOW +5;

  系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
  public static final int TYPE_SYSTEM_OVERLAY    =  FIRST_SYSTEM_WINDOW +6;

  电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。
  public static final int TYPE_PRIORITY_PHONE    =  FIRST_SYSTEM_WINDOW +7;

  系统对话框。(例如音量调节框)。
  public static final int TYPE_SYSTEM_DIALOG     =  FIRST_SYSTEM_WINDOW +8;

  锁屏时显示的对话框。
  public static final int TYPE_KEYGUARD_DIALOG   =  FIRST_SYSTEM_WINDOW +9;

  系统内部错误提示,显示于所有内容之上。
  public static final int TYPE_SYSTEM_ERROR      =  FIRST_SYSTEM_WINDOW +10;

  内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。
  public static final int TYPE_INPUT_METHOD      =  FIRST_SYSTEM_WINDOW +11;

  内部输入法对话框,显示于当前输入法窗口之上。
  public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;

  墙纸窗口。
  public static final int TYPE_WALLPAPER         = FIRST_SYSTEM_WINDOW +13;

  状态栏的滑动面板。
  public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW +14;

  系统窗口结束。
  public static final int LAST_SYSTEM_WINDOW     = 2999;

以上为转载:http://realgodo.iteye.com/blog/1780176

二、层级:
对于不同的type系统的层级处理代码:

public int windowTypeToLayerLw(int type) {
        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
            return 2;
        }
        switch (type) {
        case TYPE_UNIVERSE_BACKGROUND:
            return 1;
        case TYPE_PRIVATE_PRESENTATION:
            return 2;
        case TYPE_WALLPAPER:
            // wallpaper is at the bottom, though the window manager may move it.
            return 2;
        case TYPE_PHONE:
            return 3;
        case TYPE_SEARCH_BAR:
            return 4;
        case TYPE_RECENTS_OVERLAY:
        case TYPE_SYSTEM_DIALOG:
            return 5;
        case TYPE_TOAST:
            // toasts and the plugged-in battery thing
            return 6;
        case TYPE_PRIORITY_PHONE:
            // SIM errors and unlock.  Not sure if this really should be in a high layer.
            return 7;
        case TYPE_DREAM:
            // used for Dreams (screensavers with TYPE_DREAM windows)
            return 8;
        case TYPE_SYSTEM_ALERT:
            // like the ANR / app crashed dialogs
            return 9;
        case TYPE_INPUT_METHOD:
            // on-screen keyboards and other such input method user interfaces go here.
            return 10;
        case TYPE_INPUT_METHOD_DIALOG:
            // on-screen keyboards and other such input method user interfaces go here.
            return 11;
        case TYPE_KEYGUARD_SCRIM:
            // the safety window that shows behind keyguard while keyguard is starting
            return 12;
        case TYPE_KEYGUARD:
            // the keyguard; nothing on top of these can take focus, since they are
            // responsible for power management when displayed.
            return 13;
        case TYPE_KEYGUARD_DIALOG:
            return 14;
        case TYPE_STATUS_BAR_SUB_PANEL:
            return 15;
        case TYPE_STATUS_BAR:
            return 16;
        case TYPE_STATUS_BAR_PANEL:
            return 17;
        case TYPE_VOLUME_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return 18;
        case TYPE_SYSTEM_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return 19;
        case TYPE_NAVIGATION_BAR:
            // the navigation bar, if available, shows atop most things
            return 20;
        case TYPE_NAVIGATION_BAR_PANEL:
            // some panels (e.g. search) need to show on top of the navigation bar
            return 21;
        case TYPE_SYSTEM_ERROR:
            // system-level error dialogs
            return 22;
        case TYPE_MAGNIFICATION_OVERLAY:
            // used to highlight the magnified portion of a display
            return 23;
        case TYPE_DISPLAY_OVERLAY:
            // used to simulate secondary display devices
            return 24;
        case TYPE_DRAG:
            // the drag layer: input for drag-and-drop is associated with this window,
            // which sits above all other focusable windows
            return 25;
        case TYPE_SECURE_SYSTEM_OVERLAY:
            return 26;
        case TYPE_BOOT_PROGRESS:
            return 27;
        case TYPE_POINTER:
            // the (mouse) pointer layer
            return 28;
        case TYPE_HIDDEN_NAV_CONSUMER:
            return 29;
        }
        Log.e(TAG, "Unknown window type: " + type);
        return 2;
    }

返回值越高则Z轴层级约考上,其中 TYPE_UNIVERSE_BACKGROUND 在最低层,TYPE_HIDDEN_NAV_CONSUMER 在最上层,
从此层级中可以看出常用的两种type的区别,
TYPE_SYSTEM_ALERT 比较低层级,在系统锁屏之下,并且可以显示出系统dialog,并显示响应系统的状态栏和虚拟键盘等。
TYPE_SYSTEM_ERROR 层级较高,会盖住系统锁屏,和其它的系统级控件。

三、权限:
当我尝试设置了一些高层级的type后,发现缺少权限,于是再次调查源码看到:

public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
        int type = attrs.type;

        outAppOp[0] = AppOpsManager.OP_NONE;

        if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
            return WindowManagerGlobal.ADD_OKAY;
        }
        String permission = null;
        switch (type) {
            case TYPE_TOAST:
                // XXX right now the app process has complete control over
                // this...  should introduce a token to let the system
                // monitor/control what they are doing.
                break;
            case TYPE_DREAM:
            case TYPE_INPUT_METHOD:
            case TYPE_WALLPAPER:
            case TYPE_PRIVATE_PRESENTATION:
                // The window manager will check these.
                break;
            case TYPE_PHONE:
            case TYPE_PRIORITY_PHONE:
            case TYPE_SYSTEM_ALERT:
            case TYPE_SYSTEM_ERROR:
            case TYPE_SYSTEM_OVERLAY:
                permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
                outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
                break;
            default:
                permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
        }
        if (permission != null) {
            if (mContext.checkCallingOrSelfPermission(permission)
                    != PackageManager.PERMISSION_GRANTED) {
                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
            }
        }
        return WindowManagerGlobal.ADD_OKAY;
    }

一些低层级的type需要 SYSTEM_ALERT_WINDOW 权限,一些高层级的需要 INTERNAL_SYSTEM_WINDOW 权限。

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

但是尝试一些高层级type时加上

    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW "/>

发现没有任何效果,依然提示我没有权限。最后发现 INTERNAL_SYSTEM_WINDOW 是系统权限。系统不允许普通应用程序获得那些type。


不过最后我要说,一般来讲悬浮窗用到的type只要 TYPE_SYSTEM_ALERT 和 TYPE_SYSTEM_ERROR 就够了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值