悬浮窗设置TYPE_TOAST出现崩溃的解决方案

关于悬浮窗设置TYPE_TOAST崩溃的问题

  • 最近在做项目有用到悬浮窗,发现了一个问题,WindowManager.LayoutParams的属性设置为TYPE_TOAST在安卓7.1.1系统出现崩溃。在使用Type Toast悬浮窗的同时,使用了Toast,必现崩溃,即使catch 了Throwable也无法解决,但是假如什么都没做则不会崩溃,不过几秒后就消失了

查了一下资料发现在安卓7.1.1的系统上谷歌限制了开发者对TYPE_TOAST的滥用
这里写图片描述
google在该版本开始对TYPE TOAST进行管控,防止一个应用的悬浮窗一直悬浮在另一个应用上造成干扰

// 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);
                }
            }

从源码可以看出假如添加了TYPE_TOAST,则显示,并且设置了延迟消息,延迟时间为hideTimeoutMilliseconds

时间到了则强制隐藏

case WINDOW_HIDE_TIMEOUT:{
   final windowState window = (WindowState)msg.obj;
   synchronized(mWindowMap){
       window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
       window.hidePermanentlyLw();
       window.setDisplayLayoutNeeded();
       mWindowPlacerLocked.performSurfacePlacement();
          }
}
break;

时间到了强制隐藏~

我这里解决的方案是判断系统,如果大于7.0的话则使用TYPE_SYSTEM_ALERT来显示

   //设置type,系统提示型窗口,在应用程序之上
            if (FloatPermissionChecker.checkSDKVersion()) {
                mParmas!!.type = WindowManager.LayoutParams.TYPE_TOAST
            } else {
                mParmas!!.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
            }

这样的话就需要手动去开启设置里面的悬浮窗开关,我们代码里面可以这么写去引导用户打开悬浮窗

     val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
     //这句是重点,可以调到对应的应用界面里
     intent.data = Uri.parse("package:" + context.activity!!.packageName)
     context.startActivityForResult(intent, DeveloperComponent.PERMISSION_REQUEST, null, listener)

然后通过Settings.canDrawOverlays(application)来判断应用是否授权了悬浮窗显示权限。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值