码迷,mamicode.com
首页 > Windows程序 > 详细

WindowManager悬浮窗TYPE_TOAST

时间:2016-05-12 20:00:24      阅读:853      评论:0      收藏:0      [点我收藏+]

标签:

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无法接收触摸事件的原因也找到了.

 

 

 

WindowManager悬浮窗TYPE_TOAST

标签:

原文地址:http://blog.csdn.net/xilove102/article/details/51351868

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!