Android7.1.1对Type Toast的限制

作者: XCG00 | 来源:发表于2017-05-01 21:08 被阅读5638次

    1、现象


    目前测试中发现的现象有两种:

    • 在使用Type Toast悬浮窗的同时,使用了Toast,必现崩溃,即使catch 了Throwable也无法解决,但是将悬浮窗addView的代码注释之后则不出现崩溃;
    • 如果只有Type Toast悬浮窗,不会出现崩溃,3.5s后自动消失

    关键log如下:

    WindowManager$BadTokenException: Unable to add window -- window android.view.ViewRootImpl$W@363f7b1 has already been added

    crash log.png

    2、原因分析

    从查看google的代码发现,在25版本上有这么一个提交:

    https://android.googlesource.com/platform/frameworks/base/+/dc24f93

    从注解可以大致了解到,google在该版本开始对TYPE TOAST进行管控,防止一个应用的悬浮窗一直悬浮在另一个应用上造成干扰。

    commit.png

    在windowManager#addView的流程中:

    windowManager#addView ->
    WindowManagerImpl#addView ->
    WindowManagerGlobal#addView ->
    ViewRootImpl#setView ->
    WindowManagerService#addWindow

    在addView中会给window添加上额外的属性(这里每个版本可能会有不同的实现,这里是android7.1.1的实现)

    adJustWindowParamsLw.png

    手机上mPolicy可以直接查看PhoneWindowManager的代码实现,此时将window的params属性添加了hideTimeoutMilliseconds,值为3500ms,即最多显示3.5s

    hideTimeoutMilliseconds.png

    WindowManagerService#addWindow中会依据条件判断是否满足重复添加toast的条件,满足则返回ADD_DUPLICATE_ADD

    WindowManagerService#addWindow.png

    判断当前应用(UID)是否还有Type toast的悬浮窗在展示

    canAddToastWindowForUid.png

    在ViewRootImpl中拿到这个结果后则抛出异常:

    ViewRootImpl#setView.png

    在WindowManagerGlobal中捕获并继续抛出


    WindowManagerGlobal#addView.png

    如果没有重复添加TYPE TOAST,则显示,并设置延迟消息,延迟时间即为params中设置的最长显示时间

    add_ok.png

    时间到了之后则强制隐藏

    window_hide.png

    3、解决方案


    目前的解决方案就是在Android7.1.1上使用需要申请system alert window权限的系统级悬浮窗,或者是层级较低的TYPE_PHONE悬浮窗。

    相关文章

      网友评论

      • buhanzhe:改成 TYPE_PHONE 完美解决
      • 后来Memory:我实在统计中看到有一个用户抱着个错,我是抓破脑袋都没找到实在那个地方报错的!:sob:
        XCG00:@六_六 看看你的报错的版本是不是都是android 24呀?
        六_六:private void initWM() {
        mWM = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        mParams = new WindowManager.LayoutParams();

        // XXX This should be changed to use a Dialog, with a Theme.Toast
        // defined that sets up the layout params appropriately.
        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.windowAnimations = R.style.Animation_Toast;
        if (Build.VERSION.SDK_INT >= 24) {
        params.type = WindowManager.LayoutParams.TYPE_PHONE;
        } else {
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        }

        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        mHandler = new Handler(Looper.getMainLooper());
        }

        我们项目这样使用还是会报这个错误,很奇怪
        XCG00:@后来Memory 看样子分享还是有用的哈
      • c6fbdda457c5:阿里9游 sdk和360sdk为什么在7.1上面不需要权限也能弹出悬浮窗
        https://aligames.open.uc.cn/document/doc/detail/15
        XCG00:@fan_2017 的确是没有研究过TYPE_PHONE是怎么限制的,9游的SDK使用的也是TYPE_PHONE吗?
        c6fbdda457c5:我测试了下,n5s系统为7.1,windowmanager设置的type为TYPE_PHONE,target为22的情况下没法弹出来,必须要在手机卫士中允许才行。 然而9游的SDK直接弹出
      • 5a7a80406c4b:为啥7.1.1 有些网页放在手机上不能放大缩小
      • 两心交织的诺言:请问,我使用android模拟器,7.1.1版本的,为什么不报此类的异常的。但是我自己应用的crash报告中会出现此类错误,因为收到的并不是大面积的,我不知道是不是偶发性的,但是目前收到的此类错误都是android 7.1.1版本的。
        XCG00:@两心交织的诺言 我觉得这个是必现的,因为android源码里已经比较明显了,如果没有大规模爆发,得看你的触发几率有多少,而且7.1.1的设备占有量
        两心交织的诺言:@XCHG00OO 我看到你上面说有两个现象,第一个是,使用type_toast同时又实用Toast,意思是自己自定义一个 params.type = WindowManager.LayoutParams.TYPE_TOAST;的view,。项目中同时使用这个view以及原生的Toast导致的崩溃吗。
        XCG00: @两心交织的诺言 我没用模拟器测过,用的是pixel,google原生的系统

      本文标题:Android7.1.1对Type Toast的限制

      本文链接:https://www.haomeiwen.com/subject/yhuftxtx.html