uni-app需通过原生插件实现Android 11+悬浮窗,因MANAGE_OVERLAY_PERMISSION无法直接申请,须用Settings.canDrawOverlays()判断并跳转ACTION_MANAGE_OVERLAY_PERMISSION设置页;插件需封装checkPermission、requestPermission、show方法,并正确处理窗口标志位、触摸事件透传及后台驻留。

uni-app 本身不支持原生悬浮窗权限申请和系统层级覆盖,必须通过原生插件或自定义基座实现。
安卓 11+ 悬浮窗权限(MANAGE_OVERLAY_PERMISSION)怎么申请
Android 6.0 后,SYSTEM_ALERT_WINDOW 权限不再是安装时授予,而需运行时跳转设置页手动开启;到了 Android 11(API 30),系统进一步限制,MANAGE_OVERLAY_PERMISSION 不再能用 Intent 直接唤起设置页,必须调用 Settings.canDrawOverlays() 判断 + Settings.ACTION_MANAGE_OVERLAY_PERMISSION 跳转。
- uni-app 的
uni.getSystemInfoSync()只能拿到 API 级别,无法直接调用canDrawOverlays() - 使用
uni.openSetting()在 Android 11+ 上对悬浮窗权限无效,它只处理WRITE_EXTERNAL_STORAGE等普通权限 - 必须用原生插件封装:在 App.vue 的
onLaunch或需要展示悬浮窗前,调用插件方法检测并跳转 - 示例跳转逻辑(原生 Java):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 1001); }
uni-app 如何调用原生悬浮窗插件(非 plus.runtime)
uni-app 官方的 plus.runtime 不提供悬浮窗控制能力;实际项目中必须引入或自研原生插件(如基于 android.view.WindowManager 实现的 FloatWindow 插件),并通过 uni.requireNativePlugin() 调用。
- 插件需导出至少三个方法:
checkPermission()、requestPermission()、show()(含view参数传入 H5 页面 DOM 元素 ID) - 调用前必须确保插件已正确配置到
nativePlugins目录,并在manifest.json → app-plus → usingComponents中声明 - H5 页面内不能直接操作
WindowManager,插件内部需将 uni-app 的<view></view>渲染为SurfaceView或TextureView后 attach 到窗口 - 注意插件返回的 view 宽高单位是 px,而 uni-app 的 rpx 计算结果需提前换算(建议插件层统一按设备独立像素 dp 处理)
悬浮窗点击穿透/无法响应 touch 的常见原因
即使权限通过、窗口显示正常,用户也常遇到「点不动」「手势失效」「背景页面一起响应」等问题,核心是窗口标志位和事件分发没配对。
- 缺少
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE→ 悬浮窗抢焦点,导致背景页面失焦、input 失效 - 误加
FLAG_NOT_TOUCHABLE→ 手势完全被拦截,连点击都收不到 - 未设置
FLAG_WATCH_OUTSIDE_TOUCH或未重写onTouchEvent→ 无法感知窗口外点击,也就没法做「点击空白关闭」逻辑 - 插件未把
touchstart/move/end映射回 H5 层,uni-app 的@touchstart在悬浮窗 DOM 上不会触发(因为不是 WebView 原生节点) - 解决方案:插件内监听原生触摸事件,通过
uni.$emit()或回调函数透传坐标和类型到 JS 层
为什么真机调试时悬浮窗一闪就消失
这通常不是代码问题,而是系统级回收机制或插件生命周期管理疏漏导致的。
- Android 8.0+ 对后台服务启动有限制,若插件用
Service管理悬浮窗,未适配startForegroundService()+startForeground(),系统会在几秒后 kill 掉 - uni-app 的
onHide生命周期里,部分插件默认销毁窗口,但未判断是否处于「前台可见但应用退至后台」状态(比如按 Home 键) - 悬浮窗 View 被 GC:插件未对
View强引用,JS 层变量释放后,Java 层 View 因无引用被回收 - 多进程场景下(如推送服务单独进程),悬浮窗插件若未指定运行在主进程,会因上下文丢失而崩溃静默退出
真正难的不是让悬浮窗出来,是让它在各种锁屏、切后台、低内存场景下稳定驻留——这些细节原生插件文档几乎不提,得靠 logcat 抓 WindowManager: Window is gone 或 DeadObjectException 才能定位。

















