uni-app 官方 api 不支持 android 全局悬浮窗,必须通过原生插件实现;android 11+ 需用 settings.candrawoverlays() 检测权限并跳转至 action_manage_overlay_permission,且窗口类型、标志位、尺寸换算(rpx→dp)及触摸事件配置均须在插件层精准处理。

uni-app 官方 API 不支持 Android 全局悬浮窗,必须通过原生插件实现;直接调用 uni.openSetting() 或 plus.runtime 无效,Android 11+(API 30+)起系统已禁用隐式 Intent 跳转悬浮窗设置页。
Android 11+ 悬浮窗权限检测与跳转必须用 Settings.canDrawOverlays()
Android 6.0 开始,SYSTEM_ALERT_WINDOW 权限需运行时手动开启;到 Android 11,MANAGE_OVERLAY_PERMISSION 不再响应 Intent 直接唤起,必须先判断再跳转:
-
Settings.canDrawOverlays(context)返回false时,才需跳转设置页 - 跳转必须用
Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName())) -
uni.getSystemInfoSync().SDKVersion只能拿到 API 级别,无法替代canDrawOverlays()判断 -
uni.openSetting()在 Android 11+ 上对悬浮窗权限完全无响应,它只处理WRITE_EXTERNAL_STORAGE等普通权限
必须用原生插件封装 checkPermission、requestPermission、show 三方法
uni-app 无法直接操作 WindowManager,所有窗口创建、标志位设置、触摸透传都得在插件层完成:
- 插件需导出至少三个方法:
checkPermission()(返回 Promise)、 requestPermission()(触发跳转)、show()(接收 H5 页面 DOM ID 或 WebView URL) - 插件内部必须设置正确窗口类型:
TYPE_APPLICATION_OVERLAY(Android 8.0+),并搭配FLAG_NOT_FOCUSABLE+FLAG_NOT_TOUCH_MODAL控制交互行为 - H5 页面传入的
width/height单位是 rpx,插件需按设备独立像素(dp)换算为 px,否则尺寸严重失真 - 若使用 WebView 渲染悬浮内容,插件必须将 HTML 加载进
WebView实例,并通过addView()挂载到WindowManager,不能直接 attachSurfaceView或TextureView
悬浮窗点击失效/穿透异常的核心原因是窗口标志和事件分发配置错误
即使权限通过、窗口显示正常,用户仍常遇到「点不动」「背景页一起响应」等问题,根本不在 JS 层,而在插件的窗口参数配置:
- 未设置
FLAG_NOT_FOCUSABLE→ 悬浮窗抢焦点,导致背景页面 touch 事件丢失 - 未设置
FLAG_NOT_TOUCH_MODAL→ 所有触摸被拦截,无法穿透到底层页面 -
touchThrough: false(聚焦模式)时,必须同时设FLAG_NOT_FOCUSABLE = false,否则点击无响应 - 拖拽逻辑若用
View.setOnTouchListener()实现,需在ACTION_MOVE中主动调用windowManager.updateViewLayout(),否则位置不更新
最易被忽略的一点:插件返回的 view 尺寸单位必须统一为 dp,而 uni-app 的 rpx 计算依赖屏幕宽度,不同设备换算系数不同;若插件层不做适配,200rpx 在高端机上可能变成 400px,在低端机上只有 240px——这会导致悬浮窗错位、遮挡或缩成小点。实际开发中建议直接在插件里接收 dp 值,由 JS 层提前换算好再传入。











