uni-app需通过原生插件申请Android悬浮窗权限,Android 11+必须跳转系统设置页,配置WindowManager.LayoutParams时type用TYPE_APPLICATION_OVERLAY、flags含FLAG_NOT_FOCUSABLE、format为PixelFormat.TRANSLUCENT,并依赖自定义基座运行。

uni-app 本身不支持直接申请 Android 悬浮窗权限,SYSTEM_ALERT_WINDOW 权限必须由原生层处理,且从 Android 11(API 30)起,Settings.canDrawOverlays() 判断 + 跳转 ACTION_MANAGE_OVERLAY_PERMISSION 设置页是唯一合规路径。任何试图在 JS 层调用 requestPermissions 或硬编码 TYPE_SYSTEM_ALERT 的做法都会失败或被系统拦截。
Android 11+ 必须跳转系统设置页申请权限
Android 6.0 后 SYSTEM_ALERT_WINDOW 不再属于普通运行时权限,无法用 uni.getSystemInfo 或 plus.android.requestPermissions 获取。必须通过原生插件调用:
-
Settings.canDrawOverlays(context)判断当前是否已授权 - 未授权时,用
Intent跳转到ACTION_MANAGE_OVERLAY_PERMISSION页面(如intent://package=com.xxx.xxx#Intent;action=android.settings.action.MANAGE_OVERLAY_PERMISSION;package=com.xxx.xxx;) - 跳转后需监听
onActivityResult或使用ActivityResultLauncher回调确认结果 - 插件返回的 Promise 必须等待用户手动开启并返回 App 后才 resolve,不能假设“跳转即成功”
原生插件中 WindowManager.LayoutParams 配置要点
即使权限已获,悬浮窗仍可能不显示或无法交互,关键在 WindowManager.LayoutParams 参数组合:
-
type:Android 8.0+ 必须用TYPE_APPLICATION_OVERLAY(API 26+),TYPE_PHONE等已被废弃 -
flags:至少包含FLAG_NOT_FOCUSABLE(否则会抢焦点导致主界面失活),若需点击穿透则加FLAG_NOT_TOUCH_MODAL和FLAG_WATCH_OUTSIDE_TOUCH -
format:必须设为Pixelformat.TRANSLUCENT,否则半透明/Alpha 效果失效 -
gravity和x/y:建议初始位置避开状态栏(如y = 120),避免被系统遮挡
自定义基座是调试前提,标准基座无效
所有原生插件(包括 dh-float-window、Ba-FloatWindow、Lin-Float-Webview)都依赖自定义基座运行:
- HBuilderX 中必须勾选插件并点击「制作自定义调试基座」,耗时约 5–10 分钟
- 运行时务必选择该自定义基座,而非「运行到手机或模拟器(标准基座)」
- 修改插件 Java/UTS 代码、图标资源(如
drawable-xxhdpi/custom_icon.png)后,必须重新制作基座才能生效 - 云打包前需确认插件已在 manifest.json 的「App原生插件配置」中启用,且云端插件已绑定当前 AppID
WebView 悬浮窗通信与保活容易被忽略
用 WebView 实现 UI 的悬浮窗(如 dh-float-window)看似灵活,但存在两个隐性陷阱:
- JS 与原生通信需走
postMessage+addJavascriptInterface(Android)或 WKScriptMessageHandler(iOS),且 WebView 必须启用javascriptEnabled和domStorageEnabled - 后台驻留靠
ForegroundService+ Notification 维持进程不被杀,仅靠addView无法防止假死;插件若没实现startForeground(),切到后台几分钟后悬浮窗就会消失 - 多个悬浮窗共存时,
id必须全局唯一,否则removeView可能误删其他窗口











