Toast异常

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zh_qianwei/article/details/72723327

近期在测试时发现在某一个手机弹出Toast时候出现了这个异常,其他手机没有发现
后查看手机系统版本发现是Android 7.1,错误主要log如下

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

发生错误的使用场景如下,APP有一个渠道需要添加一个第三方的浮动的按钮,这个浮动在android 6.0以后需要一个权限ACTION_MANAGE_OVERLAY_PERMISSION,为了规避这个授权逻辑sdk里面把弹出的view改成了WindowManager.LayoutParams.TYPE_TOAS 这个类型

后来查到Google在7.1更新了些关于这个的代码,他么理由

Prevent apps to overlay other apps via toast windows

It was possible for apps to put toast type windows that overlay other apps which toast winodws aren't removed after a timeout.

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

对应代码

 // If adding a toast requires a token for this app we always schedule hiding
            // toast windows to make sure they don't stick around longer then necessary.
            // We hide instead of remove such windows as apps aren't prepared to handle
            // windows being removed under them.
            //
            // If the app is older it can add toasts without a token and hence overlay
            // other apps. To be maximally compatible with these apps we will hide the
            // window after the toast timeout only if the focused window is from another
            // UID, otherwise we allow unlimited duration. When a UID looses focus we
            // schedule hiding all of its toast windows.
            if (type == TYPE_TOAST) {
                if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
                    Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
                    return WindowManagerGlobal.ADD_DUPLICATE_ADD;
                }
                // Make sure this happens before we moved focus as one can make the
                // toast focusable to force it not being hidden after the timeout.
                // Focusable toasts are always timed out to prevent a focused app to
                // show a focusable toasts while it has focus which will be kept on
                // the screen after the activity goes away.
                if (addToastWindowRequiresToken
                        || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
                        || mCurrentFocus == null
                        || mCurrentFocus.mOwnerUid != callingUid) {
                    mH.sendMessageDelayed(
                            mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
                            win.mAttrs.hideTimeoutMilliseconds);
                }
            }

这里我们看到在弹出Toast类型view的时候 如果!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)
就会返回WindowManagerGlobal.ADD_DUPLICATE_ADD
对于这个的处理代码如下

        case WindowManagerGlobal.ADD_DUPLICATE_ADD:
            throw new WindowManager.BadTokenException(
              "Unable to add window -- window " + mWindow
                    + "has already been added");

修改意见
1:浮动的还是申请权限最好:
2:如果第三方的自己没法改又必须用,需要自己实现Toast 不能用系统的了

参考地址1
参考地址2

猜你喜欢

转载自blog.csdn.net/zh_qianwei/article/details/72723327