WindowManager悬浮窗TYPE_TOAST

来源:互联网 发布:ubuntu 命令行删除文件 编辑:程序博客网 时间:2024/05/17 00:07

WindowManager的addView是定义在接口ViewManager,同时WindowManager也是一个接口,通过Ctrl+H 看一下继承关机,发现是在WindowManagerImpl继承了WindowManager接口并实现addView方法

WindowManagerImpl.addView

 

mGlobal是WindowManagerGlobal的实例,所以调用的的是WindowManagerGlobal.addView()


代码中创建了一个ViewRootImpl实例root,并且调用root.setView传入view

在ViewRootImpl.setView里最关键的代码是


mWindowSession的类型是IWindowSession,mWindow的类型是IWindow.Stub,这句代码就是利用AIDL进行IPC,实际被调用的是Session.addToDisplay:


mServiceWindowManagerService,继续往下看


mPolicy是标记为final的成员变量:

final WindowManagerPolicy mPolicy =PolicyManager.makeNewWindowManager();

继续看PolicyManager.makeNewWindowManager,实际是Policy.makeNewWindowManager()


现在我们知道mPolicy实际上是PhoneWindowManager,那么

intres =mPolicy.checkAddPermission(attrs, appOp);

实际调用的代码是PhoneWindowManager.checkAddPermission()


TYPE_TOAST不检查permission

TYPE_PHONE检查SYSTEM_ALERT_WINDOW权限

 

TYPE_TOAST不需要权限显示悬浮窗的原因已经找到了,接着刚才addWindow方法的分析,继续看下面一句:

 

 

还是在PhoneWindowManager里的方法adjustWindowParamsLw()

注意这里我给出了三个版本的实现,一个是2.02.3.7实现的版本,一个是4.0.14.3.1实现的版本,一个是4.4实现的版本:

 

//Android 2.0 - 2.3.7 PhoneWindowManager

  public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {

    switch (attrs.type) {

      case TYPE_SYSTEM_OVERLAY:

      case TYPE_SECURE_SYSTEM_OVERLAY:

      case TYPE_TOAST:

        // These types of windows can't receive input events.

        attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        break;

    }

  }

//Android 4.0.1 - 4.3.1 PhoneWindowManager

  public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {

    switch (attrs.type) {

      case TYPE_SYSTEM_OVERLAY:

      case TYPE_SECURE_SYSTEM_OVERLAY:

      case TYPE_TOAST:

        // These types of windows can't receive input events.

        attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

        break;

    }

  }

//Android 4.4 PhoneWindowManager

  @Override

  public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {

    switch (attrs.type) {

      case TYPE_SYSTEM_OVERLAY:

      case TYPE_SECURE_SYSTEM_OVERLAY:

        // These types of windows can't receive input events.

        attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

        break;

    }

  }

 4.0.1以前,当我们使用TYPE_TOAST, Android会偷偷给我们加上FLAG_NOT_FOCUSABLEFLAG_NOT_TOUCHABLE,4.0.1开始,会额外再去掉FLAG_WATCH_OUTSIDE_TOUCH,这样真的是什么事件都没了.4.4开始, TYPE_TOAST被移除了,所以从4.4开始,使用TYPE_TOAST的同时还可以接收触摸事件和按键事件了,4.4以前只能显示出来,不能交互.

API level 18及以下使用TYPE_TOAST无法接收触摸事件的原因也找到了.

API level 18及以下可以使用TYPE_PHONE实现可以接收触摸时间的view

 

 

 

0 0