更新记录
1.0.51(2026-10-29)
- 修复 uni-app 与 uni-app x 示例页面依赖相对导入路径的问题,辅助脚本统一通过
@/uni_modules/lizhao-float-window/引用,页面可直接复制到任意业务目录。 - 修复默认本地悬浮演示依赖宿主
static文件的问题,演示 HTML 随插件提供,导入完整插件后无需额外复制辅助文件。
1.0.50(2026-10-27)
- 修复 HarmonyOS 画中画播放状态快照构造缺少可选字段导致的 ArkTS 编译失败。
- 保留会话标识、停止原因与静音的真实状态,未提供静音信息时保持未知,不误判为未静音。
1.0.49(2026-10-22)
- 新增 Android/iOS 前台
preparePictureInPicture和取消未活动准备:使用真实可见视频预览,准备成功不代表系统已进入。Home 自动进入要求 Android 12+;Android 8–11 保留autoEnterOnHome: false准备和旧手动入口。iOS 自动进入要求 14.2+ 且设备与系统允许,关闭自动进入时可在支持 PiP 的设备准备。 - 新增 Android/iOS
autoEnterOnHome准备策略:默认true,前台预览默认播放;false默认暂停,后续播放不会改变自动进入配置。Harmony 原有准备时不在前台播放的行为保留。 - 新增按当前设备和宿主动态返回的 Home 自动进入能力;准备事件与系统真实进入事件区分,沿用现有公开 API、参数和错误码。
- 修复取消或超时后旧回调影响下一视频的问题;每次准备请求只结算一次,保持
success / fail后执行complete的顺序及回调异常隔离。 - 修复 Android/iOS 暂停或播放结束后仍保留实际自动进入资格的问题;准备来源经系统恢复回 App 后保留预览并可再次 Home,直接关闭则停止播放并释放资源,原手动进入流程继续兼容。
- 修复 Android 系统画中画返回 App 后视频预览被误释放、再次按 Home 无法继续进入小窗的问题;直接关闭小窗仍正常停止播放并释放资源。
- 集成要求:升级后需重新进行包含本次原生插件的 Android/iOS 原生联编,或重新制作并安装对应自定义基座/原生包,仅更新页面资源不生效。
平台兼容性
uni-app(4.84)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.84)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | √ | √ | √ | × |
lizhao-float-window
介绍
为 uni-app / uni-app x 提供应用内悬浮、Android跨应用悬浮、可信H5通信和系统视频画中画。
补充接入说明
首次接入说明
面向 uni-app / uni-app x 的应用内悬浮窗、Android 跨应用悬浮窗和系统视频画中画插件。
如果只是第一次接入,建议先打开一个应用内小窗;确认基础能力正常后,再按本文顺序启用 Android 跨应用悬浮、H5 交互或系统画中画。
Android 支持应用内悬浮、跨应用悬浮和系统画中画;iOS、Harmony 支持应用内悬浮和系统画中画,但不支持跨应用悬浮。Web 和小程序不支持真实悬浮窗能力。
功能特色
| 功能 | 使用结果 | 相关API或配置 |
|---|---|---|
| 应用内工具窗 | 客服球、业务面板和窗口切换 | openFloatWindow / setFloatWindowDisplayMode |
| Android跨应用 | 离开App仍显示工具窗并按需唤回 | checkOverlayPermission / bringHostAppToFront |
| 窗口调整 | 拖拽、吸附、位置记忆和全屏预设 | setFloatWindowPosition / setFloatWindowSizePreset |
| H5业务通信 | 双向事件、受控文件选择与媒体权限 | onH5Message / sendMessageToH5 |
| 系统画中画 | 网络/本地视频、暂停、进度与按归属退出 | enterPictureInPicture / preparePictureInPicture / exitPictureInPicture |
完整功能说明
- 在 App 页面内显示悬浮球、客服入口、播放器或业务面板。
- 在 Android 离开 App 后继续显示工具窗、播放状态或快捷操作。
- 让悬浮 H5 页面与 App 双向传递订单、表单、客服和播放器事件。
- 让可信 H5 选择文件、拍照,或使用摄像头和麦克风。
- 将网络视频、本地视频切换到系统画中画,支持 MP4 与 HLS(m3u8)点播的起播位置和循环播放。
- 在 Android、iOS、Harmony 小窗中播放、暂停、定位点播视频,并将退出时的进度交回课程页面。
- 支持拖拽、边缘吸附、位置记忆、大小切换和自适应全屏。
- 查询权限、窗口状态和诊断信息,定位无法打开、内容未就绪或消息发送失败等问题。
适合哪些场景
客服入口、订单工具球、课程小窗、视频画中画,以及需要与App交换数据的可信H5业务面板。
| 场景 | 推荐方式 | 是否需要 Android 系统悬浮权限 | 建议起点 |
|---|---|---|---|
| 页面内显示悬浮按钮或面板 | mode: 'inApp' |
否 | 先运行下方快速开始 |
| Android 离开 App 后仍显示 | mode: 'overlay' |
是 | 先检查权限,再打开跨应用悬浮窗 |
| 自动铺满应用可用区域 | sizePreset: 'fullscreen' |
inApp 不需要 |
先用应用内模式验证布局 |
| H5 与 App 交换业务消息 | H5 消息 API | 取决于悬浮模式 | 先使用插件提供的本地 H5 |
| H5 选择文件或拍照 | 标准文件输入 | 取决于悬浮模式 | 先查询 webFileChooser |
| H5 使用摄像头或麦克风 | 允许访问设备的 HTTPS 网站来源 + webMediaPermissions |
取决于悬浮模式 | 先确认页面地址和所需能力 |
| 视频进入系统小窗 | 画中画 API | 否 | 先查询 capabilities.pip |
| 排查打开、权限或内容问题 | 状态与诊断 API | 否 | 导出当前运行信息 |
下载与导入
从插件市场导入并保留完整 uni_modules/lizhao-float-window/,API只从插件根目录导入。App原生能力须使用包含插件的自定义基座或安装包;Web/小程序按文末真实能力使用。
- 通用uni-app完整示例(选项式,Vue2/Vue3):
uni_modules/lizhao-float-window/example/uniapp/floatWindow.vue。 - uni-app x完整UTS示例:
uni_modules/lizhao-float-window/example/uniappx/index.uvue。 - 完整字段、事件、平台限制及长流程:本文对应完整示例、参数与平台说明(本文第5、6、8节)。
导入完整插件后,只需将对应示例页面复制到项目任意页面目录,并在宿主 pages.json 中注册。辅助脚本统一通过 @/uni_modules/lizhao-float-window/ 导入,本地演示资源也随插件提供,无需再复制其他辅助文件。本文最小页面可用于uni-app Vue2/Vue3;uni-app x请使用上述真实UTS页面,不直接粘贴HTML中的普通script。
完整示例按“全局悬浮 / 应用内悬浮 / 画中画”分类,依次展示常用操作、内容样式和进阶功能。在前两类的“内容样式”中,可选择经典蓝、简洁白、深色,并调整标题、背景色、文字色、字号和内容卡片圆角;先点“打开样式示例”,后续修改点“应用样式”,更新时保留已输入的备注。
这些设置用于示例网页的内容卡片,系统画中画外观由系统控制。自有网页可参照随插件提供的样式演示与 H5 消息用法接入。
完整导入与运行准备
先选择接入方式
| 你的需求 | 推荐方式 | 是否需要 Android 系统悬浮权限 | 建议起点 |
|---|---|---|---|
| 页面内显示悬浮按钮或面板 | mode: 'inApp' |
否 | 先运行下方快速开始 |
| Android 离开 App 后仍显示 | mode: 'overlay' |
是 | 先检查权限,再打开跨应用悬浮窗 |
| 自动铺满应用可用区域 | sizePreset: 'fullscreen' |
inApp 不需要 |
先用应用内模式验证布局 |
| H5 与 App 交换业务消息 | H5 消息 API | 取决于悬浮模式 | 先使用插件提供的本地 H5 |
| H5 选择文件或拍照 | 标准文件输入 | 取决于悬浮模式 | 先查询 webFileChooser |
| H5 使用摄像头或麦克风 | 允许访问设备的 HTTPS 网站来源 + webMediaPermissions |
取决于悬浮模式 | 先确认页面地址和所需能力 |
| 视频进入系统小窗 | 画中画 API | 否 | 先查询 capabilities.pip |
| 排查打开、权限或内容问题 | 状态与诊断 API | 否 | 导出当前运行信息 |
下载与导入
- 在插件市场选择“使用 HBuilderX 导入插件”。
- 确认项目中存在完整的
uni_modules/lizhao-float-window目录,不要只复制内部源码目录或修改插件目录名。 - 只从插件根目录导入 API。
uni-app 导入
// 普通 uni-app 页面只从插件根目录导入。
import {
getCapabilities,
openFloatWindow,
closeFloatWindow
} from '@/uni_modules/lizhao-float-window'
uni-app x 导入
uni-app x(UTS,保留类型标注):
// <script setup lang="uts"> 中使用相同的根目录导入方式。
import {
getCapabilities,
openFloatWindow,
closeFloatWindow
} from '@/uni_modules/lizhao-float-window'
后续示例使用两端同名 API 和参数。首次接入,或更新说明明确包含原生能力变更时,需要重新制作并安装对应平台的自定义基座或正式安装包;纯文档和页面资源更新不需要重新制作。
从基础到进阶:按业务模块使用
下列最小页面使用uni-app选项式API,兼容Vue2与Vue3。后续片段沿用FloatWindow根导入,并在相应初始化/打开成功后执行。
打开应用内小窗
<template><view><button @click="openWindow">打开应用内小窗</button></view></template>
<script>
import * as FloatWindow from '@/uni_modules/lizhao-float-window'
export default {
methods: {
openWindow() {
FloatWindow.getCapabilities({ success: (c) => {
if (!c.inApp) { console.log(c.restrictedReason); return }
FloatWindow.openFloatWindow({ mode: 'inApp', sizePreset: 'small',
content: { type: 'localAsset', value: 'uni_modules/lizhao-float-window/static/bridge-demo.html', bridgeName: 'LizhaoFloatWindow' },
fail: (e) => console.log(e.errCode, e.errMsg)
})
}, fail: (e) => console.log(e.errMsg) })
}
},
onUnload() { FloatWindow.closeFloatWindow({}) }
}
</script>
Android跨应用悬浮
由用户按钮触发权限检查;进入设置不等于已经授权,返回后重新检查再打开。
FloatWindow.checkOverlayPermission({ success: (permission) => {
if (!permission.granted) {
if (permission.canOpenSettings) FloatWindow.openOverlayPermissionSettings({})
return
}
FloatWindow.openFloatWindow({ mode: 'overlay', focusMode: 'passthrough', sizePreset: 'small',
content: { type: 'localAsset', value: 'uni_modules/lizhao-float-window/static/bridge-demo.html' },
fail: (e) => console.log(e.errMsg)
})
}, fail: (e) => console.log(e.errMsg) })
调整位置与大小
窗口打开后更新配置;输入时按需切interactive,结束输入后恢复passthrough,避免占用其他App的键盘焦点。
FloatWindow.setFloatWindowSizePreset({ preset: 'fullscreen', fail: (e) => console.log(e.errMsg) })
FloatWindow.updateFloatWindow({ dragEnabled: true, edgeSnap: true, rememberPosition: true, fail: (e) => console.log(e.errMsg) })
H5双向事件
使用已启用消息桥的可信内容。远程页面须配置精确HTTPS Origin,等待桥就绪后发送;完整网页端与文件/摄像头配置见本文后续完整说明。
FloatWindow.onH5Message({ listener: (message) => console.log('H5事件', message) })
FloatWindow.sendMessageToH5({ event: 'orderChanged', data: { id: 'demo-order' }, fail: (e) => console.log(e.errCode, e.errMsg) })
function leaveBridgePage() { FloatWindow.offH5Message({}) }
系统视频画中画
先查询pip能力;内容应为真实视频。位置为毫秒,直播不支持起播定位或循环。
FloatWindow.getCapabilities({ success: (c) => {
if (!c.pip) return
FloatWindow.enterPictureInPicture({
requestId: 'lesson:' + Date.now(), startPositionMs: 2000,
content: { type: 'url', value: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/wap2appvsnative.mp4', isVideoStream: true },
fail: (e) => console.log(e.errCode, e.errMsg)
})
}, fail: (e) => console.log(e.errMsg) })
状态与资源释放
保存实际事件/状态中的会话归属后再做控制或退出;准备取消与已活动会话退出分别处理。
FloatWindow.getFloatWindowState({ success: (state) => console.log(state), fail: (e) => console.log(e.errMsg) })
function finishOwnedPip(sessionId) {
FloatWindow.exitPictureInPicture({ expectedSessionId: sessionId, fail: (e) => console.log(e.errMsg) })
}
function finishWindow() { FloatWindow.offH5Message({}); FloatWindow.closeFloatWindow({}) }
完整业务示例与调用上下文
快速开始:打开第一个应用内悬浮窗
应用内悬浮不需要 Android 系统悬浮窗权限,适合第一次验证插件是否已经正确导入。
import {
getCapabilities,
openFloatWindow,
closeFloatWindow
} from '@/uni_modules/lizhao-float-window'
// 第一步:先确认当前平台支持应用内悬浮。
getCapabilities({
success(capabilities) {
if (!capabilities.inApp) {
console.log('当前平台不支持应用内悬浮', capabilities.restrictedReason)
return
}
// 第二步:打开插件自带的本地页面,不受网络状态影响。
openFloatWindow({
mode: 'inApp',
content: {
type: 'localAsset',
value: 'uni_modules/lizhao-float-window/static/bridge-demo.html',
bridgeName: 'LizhaoFloatWindow'
},
sizePreset: 'small',
dragEnabled: true,
edgeSnap: true,
success(res) {
console.log('应用内悬浮窗打开成功', res)
},
fail(err) {
console.log('应用内悬浮窗打开失败', err)
}
})
},
fail(err) {
console.log('读取悬浮窗能力失败', err)
}
})
// 页面离开或业务结束时主动关闭。
// closeFloatWindow({})
看到小窗后,可以继续选择下面的业务模块。若只需要应用内悬浮按钮,到这里已经完成最小接入。
按业务模块使用
模块一:客服/订单工具球
适合客服接待、订单跟进和售后处理。一个悬浮窗口可以先收起成工具球,用户点击后再展开成业务面板;切换只调整窗口尺寸,会继续保留同一 H5 页面和输入状态。宿主应用负责保存业务路由,收到 orderAction 后在前台立即处理,或回到前台的 onShow 中消费一次。
import {
openFloatWindow,
toggleFloatWindowDisplayMode,
onDisplayModeChange,
bringHostAppToFront
} from '@/uni_modules/lizhao-float-window'
const orderContent = {
type: 'localAsset',
value: 'uni_modules/lizhao-float-window/static/business-tool-demo.html',
bridgeName: 'LizhaoFloatWindow'
}
// 业务入口默认先显示为工具球。
openFloatWindow({
mode: 'inApp',
focusMode: 'interactive',
content: orderContent,
displayMode: 'ball',
ballSize: { width: 72, height: 72 },
panelSize: { width: 320, height: 420 },
size: { width: 72, height: 72 },
success() {
console.log('客服工具球已打开')
}
})
// 点击工具球时展开面板;再次调用可收回工具球。
toggleFloatWindowDisplayMode({
success(event) {
console.log('当前展示状态', event.displayMode)
}
})
onDisplayModeChange({
listener(event) {
console.log('展示状态变化', event.displayMode)
}
})
// Android overlay 用户明确点击“处理订单”后调用;页面路径由宿主自己决定。
bringHostAppToFront({ reason: 'orderAction' })
内置业务页有圆形“客服”入口、订单号和备注输入,以及发送、收起按钮。页面按窗口可见宽度适配,收起和展开只改变同一份内容的可见性;原有 bridge-demo.html 双向通信页继续独立使用。
H5 的展开、收起按钮通过消息桥请求宿主切换窗口,桥就绪后还会请求真实展示状态。将以下分支合入宿主现有的 H5 消息监听,即可连接内置业务页的按钮;这些事件属于示例业务约定。
import { onH5Message, getFloatWindowState, setFloatWindowDisplayMode, sendMessageToH5 } from '@/uni_modules/lizhao-float-window'
onH5Message({
listener(message) {
if (message.event !== 'businessReady' && message.event !== 'businessDisplayRequest') return
getFloatWindowState({
success(state) {
if (!state.opened || state.content?.value !== orderContent.value) return
const reply = (displayMode) => sendMessageToH5({
event: 'businessDisplayState',
data: { displayMode },
requestId: message.requestId || 'business-state'
})
if (message.event === 'businessReady') {
reply(state.displayMode)
return
}
const mode = message.data?.displayMode
if (mode !== 'ball' && mode !== 'panel') return
setFloatWindowDisplayMode({
displayMode: mode,
success(result) { reply(result.displayMode) }
})
}
})
}
})
H5 提交时发送用户填写的订单号和备注:{ event: 'orderAction', data: { scene: 'business-tool', orderNo: '你的订单号', remark: '处理备注' }, requestId: '请求标识' }。宿主保存待处理订单;已经在前台时立即完成路由和清理,Android overlay 跨应用场景调用 bringHostAppToFront 后等待 onShow 消费一次。完整生命周期处理见 uni_modules/lizhao-float-window/example/uniapp/floatWindow.vue 和 uni_modules/lizhao-float-window/example/uniappx/index.uvue。displayMode、ballSize、panelSize 首次启用时需要同时提供;已启用后可通过 updateFloatWindow 单独调整状态或尺寸。
模块二:让 Android 悬浮窗显示在其他应用上方
适合客服入口、播放状态、快捷工具等离开 App 后仍需显示的场景。该模式只支持 Android,并且必须由使用者在系统设置中授予“显示在其他应用上层”权限。
uni-app x(UTS,保留类型标注):
import {
checkOverlayPermission,
openOverlayPermissionSettings,
openFloatWindow,
updateFloatWindow
} from '@/uni_modules/lizhao-float-window'
// 由“打开跨应用悬浮窗”按钮调用。
function openAndroidOverlay(): void {
checkOverlayPermission({
success(permission) {
if (!permission.granted) {
// 当前函数来自明确的按钮操作,可以引导使用者进入设置页。
if (permission.canOpenSettings) {
openOverlayPermissionSettings({})
}
return
}
openFloatWindow({
mode: 'overlay',
// 默认释放输入法焦点,避免影响其他 App 输入。
focusMode: 'passthrough',
content: {
type: 'url',
value: 'https://www.dcloud.io'
},
sizePreset: 'medium',
dragEnabled: true,
edgeSnap: true,
rememberPosition: true,
keepInScreen: true,
success(res) {
console.log('Android 跨应用悬浮窗打开成功', res)
},
fail(err) {
console.log('Android 跨应用悬浮窗打开失败', err)
}
})
}
})
}
// 在悬浮窗已经打开后,由“开始输入”按钮调用。
function enableFloatWindowInput(): void {
updateFloatWindow({ focusMode: 'interactive' })
}
// 输入结束后释放焦点,避免影响其他 App。
function releaseFloatWindowInput(): void {
updateFloatWindow({ focusMode: 'passthrough' })
}
从设置页返回 App 后,应再次调用 checkOverlayPermission(),确认 granted=true 再打开。overlay 默认使用 passthrough,适合不影响其他 App 的输入;悬浮页需要输入时再切换为 interactive。inApp 默认使用 interactive。
模块三:调整大小、全屏、位置和吸附方式
适合悬浮球、业务卡片、全屏看板,以及需要记住使用者拖拽位置的场景。
Android 全局全屏会为系统栏和强制导航手势保留可操作区域,避免遮住回桌面与最近任务入口。内置聊天、样式示例可在内容页直接点“关闭”;自有网页也可通过 H5 消息请求宿主关闭窗口。
离开应用进入桌面或最近任务时,可见的全局全屏会自动收回小窗;普通全局悬浮继续显示。回到应用后保持小窗,需要时再手动切换全屏。
uni-app x(UTS,保留类型标注):
import {
setFloatWindowSizePreset,
setFloatWindowSize,
setFloatWindowPosition,
getFloatWindowPosition,
updateFloatWindow
} from '@/uni_modules/lizhao-float-window'
// 由“全屏”按钮调用,只完成一个目标。
function useFullscreen(): void {
setFloatWindowSizePreset({
preset: 'fullscreen',
success(res) {
console.log('已切换为自适应全屏', res)
}
})
}
// 由“自定义尺寸”按钮调用。
function useCustomCardSize(): void {
setFloatWindowSize({
size: { width: 300, height: 180 }
})
}
// 由“移动窗口”按钮调用;移动成功后再读取坐标。
function moveFloatWindow(): void {
setFloatWindowPosition({
position: { x: 20, y: 120 },
success() {
getFloatWindowPosition({
success(position) {
console.log('当前悬浮窗坐标', position)
}
})
}
})
}
// 由“记住位置”开关调用。
function enablePlacementPreferences(): void {
updateFloatWindow({
edgeSnap: true,
rememberPosition: true,
keepInScreen: true,
edgePadding: 16
})
}
fullscreen 会铺满当前应用的安全可用区域,并随横竖屏或窗口尺寸变化更新;它不会覆盖状态栏、刘海或系统导航区域,并且在全屏状态下不响应拖拽。自定义 width / height 只接受数字,Android 使用 px、iOS 使用 pt、Harmony 使用 vp。
Android 应用内模式下,自定义 size 的宽、高均覆盖当前完整窗口且 keepInScreen: true 时,窗口会从左上角对齐,键盘开合保持窗口位置稳定。自定义尺寸仍保留传入值;需要随横竖屏或窗口大小自动适配时,使用 fullscreen。
首次打开时如已有键盘且无法确定完整窗口尺寸,会保留普通自定义窗口的定位方式;收起键盘后重新设置 size 或重新打开悬浮窗,可重新计算对齐位置。
模块四:监听交互并动态切换内容
适合点击悬浮球打开业务页、记录拖拽坐标,或在远程页面与本地页面之间切换。
uni-app x(UTS,保留类型标注):
import {
onMove,
offMove,
onClick,
offClick,
setFloatWindowContent
} from '@/uni_modules/lizhao-float-window'
onMove({
listener(event) {
console.log('悬浮窗移动到', event.x, event.y)
}
})
onClick({
listener(event) {
console.log('悬浮窗被点击', event)
}
})
setFloatWindowContent({
content: {
type: 'url',
value: 'https://www.dcloud.io'
},
success(res) {
console.log('悬浮窗内容切换成功', res)
}
})
// 在页面卸载钩子中调用,不要在注册后立即执行。
function cleanupFloatWindowListeners(): void {
offMove({})
offClick({})
}
常用内容类型为远程网页 url 和应用资源 localAsset。localFile 不是通用网页路径,当前对外保证仅用于 Harmony 应用自己的视频文件。
模块五:让 H5 与 App 双向传递消息
适合订单提交、客服会话、播放器状态同步和表单操作。推荐先使用插件提供的本地 H5 验证通信顺序。
import {
onH5Message,
offH5Message,
openFloatWindow,
sendMessageToH5
} from '@/uni_modules/lizhao-float-window'
// 先订阅,再打开页面,避免漏掉 H5 初始化消息。
onH5Message({
listener(message) {
console.log('App 收到 H5 消息', message)
}
})
openFloatWindow({
mode: 'inApp',
content: {
type: 'localAsset',
value: 'uni_modules/lizhao-float-window/static/bridge-demo.html',
bridgeName: 'LizhaoFloatWindow'
},
success() {
sendMessageToH5({
event: 'appGreeting',
data: { text: '你好,H5' },
requestId: 'req-app-001',
success(result) {
console.log('消息已交给当前 H5 页面', result)
}
})
}
})
// 页面卸载时取消监听。
// offH5Message({})
H5 侧通过桥对象发送 JSON 字符串,并监听固定事件接收 App 消息:
window.LizhaoFloatWindow.postMessage(JSON.stringify({
event: 'submitOrder',
data: { orderNo: 'DEMO-001' },
requestId: 'req-h5-001'
}))
window.addEventListener('lizhaoFloatWindowMessage', function (event) {
console.log('H5 收到 App 消息', event.detail)
})
远程 H5 必须使用 HTTPS,并配置精确 Origin,例如 allowedOrigins: ['https://example.com']。Origin 只能包含协议、域名和可选端口,不能包含路径、查询、片段、通配符或 Token。单条序列化消息最大 256 KB;派发成功只表示消息已交给当前页面,不代表 H5 业务已经处理完成。
模块六:让 H5 选择文件、拍照或使用音视频设备
文件选择与拍照
H5 继续使用标准文件输入,不需要调用私有上传 API:
<!-- 相册单选或多图选择 -->
<input id="gallery" type="file" accept="image/*" multiple />
<!-- 优先请求系统拍照,具体入口由当前系统文件选择界面决定 -->
<input id="camera" type="file" accept="image/*" capture="environment" />
<script>
document.querySelector('#gallery').addEventListener('change', function (event) {
const files = Array.from(event.target.files || [])
console.log('本次选择图片数量', files.length)
})
</script>
Android 支持标准文件选择、拍照和多图返回;iOS、Harmony 保留系统默认文件选择界面。接入前可以读取 webFileChooser,不要把它和摄像头/麦克风实时采集能力混为一类。
摄像头和麦克风
Android、iOS 的可信 H5 可以按精确 HTTPS Origin 申请摄像头和麦克风。系统权限已经允许时,仍然需要在本次 content 中配置网页媒体白名单:
import { openFloatWindow } from '@/uni_modules/lizhao-float-window'
openFloatWindow({
mode: 'inApp',
content: {
type: 'url',
value: 'https://rtc.example.com/room',
allowedOrigins: ['https://rtc.example.com'],
webMediaPermissions: ['camera', 'microphone']
},
success(res) {
console.log('音视频 H5 已打开', res)
},
fail(err) {
console.log('音视频 H5 打开失败', err)
}
})
webMediaPermissions未配置或为空时,插件会拒绝全部网页媒体采集。- 只使用一种设备时,可以只配置
['camera']或['microphone']。 - 媒体采集不要求
bridgeName;只有页面还需要和 App 收发业务消息时才配置消息桥。 - 页面位于 iframe 内时,父页面还需要设置
allow="camera; microphone"。 - Harmony 当前
webMediaCapture=false,不要在该平台展示网页摄像头或麦克风入口。
Android H5 自动播放
Android 悬浮网页默认要求用户手势后再播放媒体。确有自动播放需求时,可以在打开页面前设置:
import { setMediaPlaybackRequiresUserGesture } from '@/uni_modules/lizhao-float-window'
setMediaPlaybackRequiresUserGesture({
required: false,
success(res) {
console.log('Android 媒体播放手势策略已设置', res)
},
fail(err) {
console.log('当前平台不支持该设置', err)
}
})
required 的安全默认值为 true。打开悬浮网页前设置时,返回的 appliedToCurrentWebView=false 表示配置已保存,将用于下一次创建;网页已经打开并成功应用时返回 true。该方法只支持 Android,其他平台返回 9015001。它不会自动重试之前已经失败的 play(),也不能替代摄像头和麦克风的 webMediaPermissions 配置。
模块七:让视频进入系统画中画
适合课程、直播和视频播放。调用前先确认 capabilities.pip=true,并把真实视频内容标记为 isVideoStream: true。
import {
getCapabilities,
enterPictureInPicture,
exitPictureInPicture
} from '@/uni_modules/lizhao-float-window'
getCapabilities({
success(capabilities) {
if (!capabilities.pip) {
console.log('当前设备不支持系统画中画')
return
}
enterPictureInPicture({
content: {
type: 'url',
value: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/wap2appvsnative.mp4',
isVideoStream: true
},
// MP4 或 HLS 点播从第 2 秒开始,单位为毫秒。
startPositionMs: 2000,
success(res) {
console.log('已进入系统画中画', res)
},
fail(err) {
console.log('进入系统画中画失败', err)
}
})
}
})
// 业务结束时退出画中画。
// exitPictureInPicture({})
如果项目使用统一的窗口入口,也可以把同样的点播参数放在 openFloatWindow 或 updateFloatWindow 中:
openFloatWindow({
mode: 'pip',
content: {
type: 'url',
value: 'https://example.com/video.mp4',
isVideoStream: true
},
startPositionMs: 2000,
loop: false
})
startPositionMs 适用于可定位的 MP4、HLS 点播视频。点播媒体会在系统画中画开始播放前完成初始跳转;循环播放回到视频开头,startPositionMs 只控制首次起播。实际定位精度取决于媒体和系统播放器。
m3u8 点播与直播
从 1.0.46 起,Android、iOS、Harmony 会在播放器准备完成后识别 HLS 点播或直播,m3u8 后缀不再代表直播。已有 startPositionMs 调用无需调整:
import { openFloatWindow } from '@/uni_modules/lizhao-float-window'
// 公开 HLS 点播示例;生产项目替换为自己的 m3u8 地址。
openFloatWindow({
mode: 'pip',
content: {
type: 'url',
value: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
isVideoStream: true
},
startPositionMs: 2000,
loop: false,
success: res => console.log('HLS 点播已进入画中画', res),
fail: err => console.log('HLS 播放失败', err)
})
content.liveMode 不填或传 auto 时自动识别;已知直播可传 live,已知点播可传 vod。该字段不能让不可定位的直播流支持跳转。isVideoStream: true 表示视频内容,与直播/点播无关。
显式声明点播后,若 iOS 仍无法取得有效时长,带起播或循环的请求会返回 9015008;请确认资源确实为可定位的点播。
| 媒体 | Android / iOS | Harmony |
|---|---|---|
| 可定位的 HLS 点播 | 支持 startPositionMs、loop |
支持起播、循环及原有播放控制 |
| 真正直播或无法确认时长的流 | 自动模式按直播处理,忽略起播和循环 | 不支持跳转或循环,传入非零起播或循环时返回 9015007 |
HLS 地址、播放列表和分片都需要可访问,编码需由系统播放器支持;本插件不提供 DRM 授权能力。升级 1.0.46 后需重新制作并安装 Android/iOS 自定义基座或安装包,Harmony 重新构建 HAP。
插件自带的 uni-app 与 uni-app x 示例均提供“HLS 点播 2 秒起播”和“HLS 点播循环播放”按钮,前者演示自动识别,后者演示 liveMode: 'vod'。原有 MP4 与 enterPictureInPicture 入口继续保留。
Android 需要 Android 8.0 及以上,并且设备与当前 App 页面都允许画中画。iOS、Harmony 也以当前设备的 capabilities.pip 为准。普通网页、图片和业务卡片不能伪装成画中画成功,应继续使用应用内悬浮或 Android 跨应用悬浮。
播放、暂停与点播定位
Android、iOS、Harmony 都可通过同一组 API 播放、暂停、跳转点播并查询状态。适合课程小窗、直播控制台和页面进度同步;先通过 getCapabilities 判断当前设备与基座是否支持。
| 场景 | Android | iOS | Harmony |
|---|---|---|---|
| 播放、暂停、状态、进度事件 | 支持 | 支持 | 支持 |
| MP4 / HLS 点播 seek | 支持 | 支持 | 支持 |
| 系统小窗控制 | 播放/暂停、点播前后 10 秒,布局由系统决定 | 使用系统 AVKit 控件 | 使用系统 PiP 模板 |
| 退出时返回最后快照 | 支持 | 支持 | 支持 |
| 预准备(关闭 Home 自动进入) | 1.0.49:Android 8.0+ | 1.0.49:设备支持 PiP 时可用 | 支持 |
| Home 自动进入 | 1.0.49:Android 12+ | 1.0.49:iOS 14.2+,设备与系统允许 | 1.0.48 起支持 |
先使用前面的示例进入画中画,再将以下方法分别绑定到播放、暂停按钮。能力字段表示设备支持,state.prepared 表示当前播放器已经准备;按钮需要同时满足这两个条件。
import { pausePictureInPicture, playPictureInPicture } from '@/uni_modules/lizhao-float-window'
function pauseCourse() {
pausePictureInPicture({
success: state => console.log('已暂停,当前位置(毫秒)', state.positionMs),
fail: err => console.log('暂停失败', err)
})
}
function playCourse() {
playPictureInPicture({
success: state => console.log('当前是否播放', state.playing),
fail: err => console.log('播放失败', err)
})
}
点播跳转先查询当前状态;直播或不可定位媒体隐藏跳转按钮。下面只完成“跳到第 10 秒”这一项操作。
import { getPictureInPicturePlaybackState, seekPictureInPicture } from '@/uni_modules/lizhao-float-window'
function jumpToTenSeconds() {
getPictureInPicturePlaybackState({
success(state) {
if (!state.prepared || !state.seekable || state.isLive) return
seekPictureInPicture({
positionMs: 10000,
success: result => console.log('跳转后位置(毫秒)', result.positionMs),
fail: err => console.log('跳转失败', err)
})
}
})
}
seekPictureInPicture 在原生完成定位后才成功,暂停中的点播跳转后仍保持暂停。负数、非有限位置返回 9015002;未准备返回 9015005;直播不允许 seek,返回 9015007;原生失败或跳转超时返回 9015008。空闲时查询成功返回 prepared=false、active=false、sourceType=null 和零进度。
Harmony 定位超时后会等待该次原生定位结束,再接受下一次定位;期间播放、暂停和退出仍可用。再次定位返回 9015008 时,请稍后重试;持续失败可退出后重新进入。
前台准备后按 Home 自动进入
适合先在 App 内观看视频、离开 App 时继续以系统小窗播放。1.0.48 仅 Harmony 支持准备和 Home 自动进入;1.0.49 补齐 Android/iOS 的前台准备和 Home 自动进入能力。 使用上述能力需要包含本次原生插件的 Android/iOS 自定义基座或原生安装包。
Android 自动进入要求 Android 12 及以上;Android 8–11 可使用 autoEnterOnHome: false 前台准备和原有手动进入。iOS 自动进入要求 iOS 14.2 及以上,且设备与系统设置允许;关闭自动进入时,设备支持 PiP 即可准备。getCapabilities 返回的 pipAutoEnterOnHome 按当前设备和宿主动态返回,能力支持不代表当前已经进入小窗。
在 App 前台由用户按钮调用准备,等待真实 success 后再按 Home 或切换应用。Android/iOS 的 autoEnterOnHome: true 会显示真实视频预览并默认播放,false 则准备预览并默认暂停,之后调用播放也不会把自动进入配置改为 true。Harmony 保留准备时不在前台播放、系统进入后播放的行为。
preparePictureInPicture 仅管理插件自己的原生播放器,不会自动接管页面 <video>、H5 或其他播放器。业务续播时通过 startPositionMs 交接毫秒进度,并协调原播放器暂停,避免两边同时出声。
import {
getCapabilities,
preparePictureInPicture,
cancelPictureInPicturePreparation
} from '@/uni_modules/lizhao-float-window'
// 绑定页面前台的“启用 Home 小窗”按钮。
function prepareHomePip() {
getCapabilities({
success(capabilities) {
if (capabilities.pipAutoEnterOnHome !== true) {
console.log('当前设备或基座不支持 Home 自动进入,请使用手动小窗入口')
return
}
preparePictureInPicture({
content: {
type: 'url',
value: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/wap2appvsnative.mp4',
isVideoStream: true
},
autoEnterOnHome: true,
success(state) {
console.log('媒体已准备,请按 Home 验证;是否已进入以系统状态为准', state)
},
fail(err) {
console.log('准备失败,请回到前台检查媒体与系统设置', err)
}
})
},
fail(err) {
console.log('读取 Home 自动进入能力失败', err)
}
})
}
// 单独绑定“取消准备”按钮,由用户决定何时取消。
function cancelHomePipPreparation() {
cancelPictureInPicturePreparation({
success: state => console.log('未进入的小窗准备已取消', state),
fail: err => console.log('取消准备失败,活动小窗请使用退出接口', err)
})
}
准备成功或收到 pipPrepared 只表示媒体就绪;只有 pipStarted 或查询得到 active=true 才表示系统已确认进入。Android/iOS 必须保留前台可见预览,首次初始化不要放在 onHide,也不要在 onHide 中补调 enterPictureInPicture 来替代准备流程。
Android/iOS 暂停或播放完成会撤销实际自动进入资格,但不修改会话的 autoEnterOnHome 配置;恢复播放且系统条件满足后可重新具备资格。准备来源的小窗通过系统恢复回 App 后保留可见预览,符合条件时可以再次按 Home;直接关闭小窗会停止播放并释放资源。
cancelPictureInPicturePreparation 只取消尚未进入的准备态;进入中或已经活动时返回 9015005,应使用 exitPictureInPicture。直播仍只支持播放与暂停,不使用点播定位或循环。
查看播放状态和进度
适合显示课程进度、播放状态或同步业务记录。查询接口返回真实播放器快照;连续更新通过 onContentEvent 接收,在进入时用 progressIntervalMs 设置间隔。
import { getPictureInPicturePlaybackState } from '@/uni_modules/lizhao-float-window'
getPictureInPicturePlaybackState({
success(state) {
console.log('已准备', state.prepared, '正在播放', state.playing)
console.log('位置/时长(毫秒)', state.positionMs, state.durationMs)
}
})
事件包为 { data, active, preparing, playerState, timestamp };普通播放事件的 data 是播放快照,pipStopped 的 data 是 { reason, snapshot },其中 snapshot 取自播放器释放前。下面为 uni-app 的事件读取示例;uni-app x 的强类型事件读取见完整示例。
import { onContentEvent, offContentEvent } from '@/uni_modules/lizhao-float-window'
onContentEvent({
listener(event) {
const data = event.payload && event.payload.data
if (!data) return
if (event.name === 'pipProgress') {
console.log('当前进度(毫秒)', data.positionMs)
}
}
})
// 页面卸载时调用 offContentEvent({})。
将小窗进度交回课程页面
适合“页面看课程 → 进入小窗 → 返回页面”的业务。进入前暂停页面视频,并传入它的毫秒进度;停止时将快照交给页面播放器。请保留页面 <video> 实例,折叠模块时使用 v-show,避免丢失播放器。
下面为 uni-app 的最小交接示例,页面视频的 id 为 courseVideo。startCoursePip 接收页面记录的进度和播放状态;页面卸载时设置 pageAlive=false 并移除监听。接入多个业务入口时,每次启动新媒体都应更新业务操作标识,防止旧续播任务影响新媒体。
import { enterPictureInPicture, pausePictureInPicture, onContentEvent, offContentEvent } from '@/uni_modules/lizhao-float-window'
import { nextTick } from 'vue'
import { onUnload } from '@dcloudio/uni-app'
const courseVideo = uni.createVideoContext('courseVideo')
let pageAlive = true
let coursePipOwned = false
let operation = 0
function startCoursePip(positionMs, wasPlaying) {
const current = ++operation
coursePipOwned = true
courseVideo.pause()
enterPictureInPicture({
content: {
type: 'url',
value: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/wap2appvsnative.mp4',
isVideoStream: true,
liveMode: 'vod'
},
startPositionMs: positionMs,
progressIntervalMs: 500,
success() {
if (!pageAlive || current !== operation || !coursePipOwned) return
if (!wasPlaying) pausePictureInPicture({})
},
fail() {
if (!pageAlive || current !== operation) return
coursePipOwned = false
if (wasPlaying) courseVideo.play()
}
})
}
onContentEvent({
listener(event) {
if (!pageAlive || !coursePipOwned || event.name !== 'pipStopped') return
const data = event.payload && event.payload.data
if (!data || !data.snapshot) return
coursePipOwned = false
const current = operation
const state = data.snapshot
const resume = (data.reason === 'restore' || data.reason === 'api') && state.playing
nextTick(() => {
if (!pageAlive || current !== operation || coursePipOwned) return
courseVideo.seek(state.positionMs / 1000)
if (resume) courseVideo.play()
else courseVideo.pause()
})
}
})
onUnload(() => {
pageAlive = false
operation++
offContentEvent({})
})
restore 表示系统发起返回应用的恢复流程,api 表示主动调用退出,system 表示系统关闭或无法确定返回原因;取消准备还可能返回 cancel。仅在恢复/主动退出且停止前正在播放时续播;系统关闭、出错或原先暂停时保持暂停。退出快照可能保留 active=true,因为它描述退出前的状态;事件外层 active=false。退出后重新查询真实状态:资源已释放时为空闲;Android/iOS 准备来源经系统恢复回 App 时可保留 prepared 预览,避免再启动页面播放器造成重复播放。iOS 原有 pipEntered / pipExited 继续保留。
这是页面与系统播放器之间的进度交接,实际定位精度由媒体与系统决定。完整示例还处理了暂停课程、异步回调、页面卸载和新媒体启动。
直播只提供播放与暂停
适合真实直播地址进入小窗。填写自己的直播 URL,显式声明 liveMode: 'live';不设置起播位置或循环。
uni-app x(UTS,保留类型标注):
import { enterPictureInPicture } from '@/uni_modules/lizhao-float-window'
function startLive(liveUrl: string) {
enterPictureInPicture({
content: { type: 'url', value: liveUrl, isVideoStream: true, liveMode: 'live' },
loop: false,
progressIntervalMs: 1000,
success: result => console.log('直播已进入小窗', result),
fail: err => console.log('直播进入失败', err)
})
}
完整示例提供默认展开的课程/直播入口,按真实准备状态启用控制,直播隐藏普通定位按钮;高级演示保留直播定位失败、MP4/HLS、循环和 Home 自动进入等验证操作。见 uni_modules/lizhao-float-window/example/uniapp/floatWindow.vue 与 uni_modules/lizhao-float-window/example/uniappx/index.uvue。
模块八:在 Harmony 播放本地或鉴权视频
Harmony 还提供应用资源视频、应用自己目录中的 MP4 和带请求头的网络视频。播放控制、状态查询及 Home 自动进入参见上方三端模块。
本地与鉴权视频
import { enterPictureInPicture } from '@/uni_modules/lizhao-float-window'
// 播放随应用发布的视频。
enterPictureInPicture({
content: {
type: 'localAsset',
value: 'uni_modules/lizhao-float-window/static/pip-test.mp4',
isVideoStream: true
}
})
// 播放需要临时请求凭据的网络视频。
enterPictureInPicture({
content: {
type: 'url',
value: 'https://example.com/protected.mp4',
headers: {
Authorization: 'Bearer <由业务安全获取的临时凭据>'
},
isVideoStream: true
}
})
下载后的视频可以使用 localFile,但当前对外保证仅接受 Harmony 当前应用自己 files/cache/temp 目录内的普通 MP4;不支持任意系统绝对路径、目录、符号链接或跨应用文件。不要把长期 Token、密钥或生产凭据写入页面、README 或代码仓库。
模块九:查询状态并收集诊断信息
适合判断窗口是否已经打开、当前是否可见,或排查权限、内容加载、网页媒体和消息通信问题。
import {
getCapabilities,
getFloatWindowState,
getFloatWindowDiagnostics
} from '@/uni_modules/lizhao-float-window'
getCapabilities({
success(res) {
console.log('当前平台能力', res)
}
})
getFloatWindowState({
success(res) {
console.log('当前悬浮窗状态', res)
}
})
getFloatWindowDiagnostics({
success(res) {
console.log('当前运行诊断', res)
}
})
诊断结果可能包含当前窗口、页面 Origin、权限和最近错误摘要。提供给技术支持前,请先确认其中没有业务不希望对外提供的信息。
完整示例
- uni_modules/lizhao-float-window/example/uniapp/floatWindow.vue
- uni_modules/lizhao-float-window/example/uniappx/index.uvue
- 插件目录
uni_modules/lizhao-float-window/static/bridge-demo.html:H5 与 App 双向通信示例。 - 插件目录
uni_modules/lizhao-float-window/static/pip-test.mp4:本地视频画中画示例。
完整示例覆盖应用内与 Android 跨应用悬浮、大小和位置、拖拽、内容切换、H5 通信、网页媒体、系统画中画、播放控制和诊断。业务页面仍应只从插件根目录导入 API。
Android:暂停进入与按归属退出
需要从课程播放器交接到系统小窗时,可在进入前指定播放意图,并按请求独立查询状态。先确认原播放器实际暂停;按小窗实际位置恢复原播放器的完整用法见播放器插件附带的两套示例。
import { enterPictureInPicture, exitPictureInPicture } from '@/uni_modules/lizhao-float-window'
const requestId = 'course:' + Date.now() // 每次操作生成新键,勿复用
enterPictureInPicture({
requestId,
content: { type: 'url', value: 'https://example.com/course.mp4', isVideoStream: true, liveMode: 'vod' },
startPositionMs: 12000,
autoplay: false,
muted: true
})
// 用户取消本次操作或所属页面卸载时。
function cancelThisRequest() {
exitPictureInPicture({ expectedRequestId: requestId })
}
| 可选项 | 业务用途 | 省略时 |
|---|---|---|
| enter.autoplay | false 使准备和进入阶段保持暂停,之后可用播放控制开始 | true,保留旧行为 |
| enter.muted | 准备前应用静音 | false |
| enter.requestId | 首个原生事件前也能取消当前请求;1–128 位 ASCII 字母、数字或 . _ : - | 不设置调用者请求键 |
| 查询的 expectedRequestId | 按请求读取当前状态或最近 120 秒内的终态 | 保留当前窗口查询 |
| 控制/查询/退出的 expectedSessionId | 仅操作实际原生会话,失效即失败 | 保留旧的当前窗口调用 |
| exit.expectedRequestId | 按请求取消准备或关闭;与 expectedSessionId 互斥 | 不做请求归属匹配 |
使用 getPictureInPicturePlaybackState({ expectedRequestId, success }) 以短回调查询当前/最终状态,查询不占用全局监听。终态缓存最多 128 项,满时淘汰最老终态,过期或无匹配返回 9015005;不要据此恢复旧进度。最终状态 stoppedReason 非空,playing 保留释放前实际值。活动时 stoppedReason 为空。请求键未过期的终态仍存在时,不接受同键重用。
Android 的准备、活动和停止事件携带原生 sessionId 与调用者 requestId;播放状态快照也提供这两个可选字段和实际 muted。空闲 ID 为 null。pipPreparing 仅表示已受理,pipStarted 才表示实际进入。停止事件的 payload.data.snapshot 是释放前最终状态。请求键用于取消归属,不是鉴权凭据;不要包含视频地址、账号或密钥。
提前取消会在 120 秒内阻止同键迟到进入;最多保存 128 条有效取消记录,容量满时明确失败,不驱逐仍有效记录。取消失败时保持原播放器暂停,确认小窗关闭后再恢复。任一准备或活动会话占用本插件的小窗入口,新请求不会替换旧会话。
上述新增选项仅供 Android 的 uni-app / uni-app x 使用,安装包须包含当前原生实现。其他平台传入这些选项明确返回不支持;省略选项保留各平台既有行为。系统画中画播放器当前不交接倍速、镜像、原播放器弹幕、试看或列表连播。
API 用途速查
| 模块 | 常用 API | 用途 |
|---|---|---|
| 能力判断 | getCapabilities |
接入前读取当前平台的悬浮、PiP、H5 桥、媒体采集和文件选择能力。 |
| 悬浮窗生命周期 | openFloatWindow、updateFloatWindow、closeFloatWindow |
打开、动态更新和关闭悬浮窗。 |
| 业务展示状态 | setFloatWindowDisplayMode、toggleFloatWindowDisplayMode、onDisplayModeChange、offDisplayModeChange |
在工具球和业务面板之间切换,并监听真实状态变化。 |
| 宿主唤回 | bringHostAppToFront |
Android overlay 在明确业务操作后请求宿主回到前台;业务路由由宿主自己处理。 |
| 显示与层级 | showFloatWindow、hideFloatWindow、bringFloatWindowToFront |
控制显隐和应用内层级。 |
| 位置与尺寸 | setFloatWindowPosition、getFloatWindowPosition、setFloatWindowSize、setFloatWindowSizePreset |
调整坐标、自定义尺寸或切换尺寸预设。 |
| 拖拽 | setFloatWindowDragEnabled、onMove、offMove |
控制拖拽并监听坐标。 |
| 内容切换 | setFloatWindowContent |
在远程 URL、本地 HTML 和受支持的本地媒体之间切换。 |
| Android 播放策略 | setMediaPlaybackRequiresUserGesture |
控制 Android 悬浮网页是否必须由用户手势触发媒体播放。 |
| H5 双向通信 | onH5Message、sendMessageToH5、offH5Message |
H5 与 App 交换结构化业务事件。 |
| 内容事件 | onContentEvent、offContentEvent |
监听页面加载和系统画中画内容事件。 |
| 系统画中画 | enterPictureInPicture、exitPictureInPicture |
在当前设备支持时进入或退出系统画中画。 |
| 三端画中画控制 | playPictureInPicture、pausePictureInPicture、seekPictureInPicture、getPictureInPicturePlaybackState |
播放、暂停、点播跳转和真实状态查询。 |
| 画中画准备 | preparePictureInPicture、cancelPictureInPicturePreparation |
前台准备、取消未活动准备和 Home 自动进入;平台范围见模块七。 |
| 权限与诊断 | checkOverlayPermission、openOverlayPermissionSettings、getFloatWindowState、getFloatWindowDiagnostics |
检查 Android 跨应用悬浮权限并获取运行状态或诊断信息。 |
| 点击事件 | onClick、offClick |
监听或取消悬浮窗点击事件。 |
| 兼容别名 | open / setConfig / close / show / hide / toFront / setPosition / getPosition / setSize / setDragEnable / setShowPattern / setContent |
保留旧调用;新接入优先使用完整方法名。 |
常用参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| mode | string | 否 | 窗口模式,建议显式传入 | Android为overlay;iOS/Harmony为inApp | inApp / overlay / pip |
| sizePreset | string | 否 | 窗口尺寸预设 | 按平台默认,建议显式传入 | small / medium / large / custom / fullscreen |
| startPositionMs | number | 否 | 点播起播位置,毫秒 | 0 | 非负数 |
| autoplay | boolean | 否 | Android/iOS准备或进入后的播放意图 | true | true / false |
| muted | boolean | 否 | Android/iOS初始静音 | false | true / false |
全部可选项、回调字段和默认行为见 本文对应完整示例、参数与平台说明;公开类型定义位于 uni_modules/lizhao-float-window/utssdk/interface.uts。
完整参数、返回值与事件
常用 API 与配置
API 用途总览
| 模块 | 常用 API | 用途 |
|---|---|---|
| 能力判断 | getCapabilities |
接入前读取当前平台的悬浮、PiP、H5 桥、媒体采集和文件选择能力。 |
| 悬浮窗生命周期 | openFloatWindow、updateFloatWindow、closeFloatWindow |
打开、动态更新和关闭悬浮窗。 |
| 业务展示状态 | setFloatWindowDisplayMode、toggleFloatWindowDisplayMode、onDisplayModeChange、offDisplayModeChange |
在工具球和业务面板之间切换,并监听真实状态变化。 |
| 宿主唤回 | bringHostAppToFront |
Android overlay 在明确业务操作后请求宿主回到前台;业务路由由宿主自己处理。 |
| 显示与层级 | showFloatWindow、hideFloatWindow、bringFloatWindowToFront |
控制显隐和应用内层级。 |
| 位置与尺寸 | setFloatWindowPosition、getFloatWindowPosition、setFloatWindowSize、setFloatWindowSizePreset |
调整坐标、自定义尺寸或切换尺寸预设。 |
| 拖拽 | setFloatWindowDragEnabled、onMove、offMove |
控制拖拽并监听坐标。 |
| 内容切换 | setFloatWindowContent |
在远程 URL、本地 HTML 和受支持的本地媒体之间切换。 |
| Android 播放策略 | setMediaPlaybackRequiresUserGesture |
控制 Android 悬浮网页是否必须由用户手势触发媒体播放。 |
| H5 双向通信 | onH5Message、sendMessageToH5、offH5Message |
H5 与 App 交换结构化业务事件。 |
| 内容事件 | onContentEvent、offContentEvent |
监听页面加载和系统画中画内容事件。 |
| 系统画中画 | enterPictureInPicture、exitPictureInPicture |
在当前设备支持时进入或退出系统画中画。 |
| 三端画中画控制 | playPictureInPicture、pausePictureInPicture、seekPictureInPicture、getPictureInPicturePlaybackState |
播放、暂停、点播跳转和真实状态查询。 |
| 画中画准备 | preparePictureInPicture、cancelPictureInPicturePreparation |
前台准备、取消未活动准备和 Home 自动进入;平台范围见模块七。 |
| 权限与诊断 | checkOverlayPermission、openOverlayPermissionSettings、getFloatWindowState、getFloatWindowDiagnostics |
检查 Android 跨应用悬浮权限并获取运行状态或诊断信息。 |
| 点击事件 | onClick、offClick |
监听或取消悬浮窗点击事件。 |
为兼容已经接入的项目,插件仍保留 open / setConfig / close / show / hide / toFront / setPosition / getPosition / setSize / setDragEnable / setShowPattern / setContent 等别名。新项目建议使用上表中的完整 API 名称。
通用回调
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
success |
function | 否 | 当前 API 按平台规则确认成功时触发。 | 无 | 无 |
fail |
function | 否 | 参数、权限、平台能力或系统操作失败时触发。 | 无 | 无 |
complete |
function | 否 | 调用结束后触发,成功或失败都会执行。 | 无 | 无 |
打开与更新参数
openFloatWindow(options) 使用完整参数;updateFloatWindow(options) 使用同名可选字段动态更新已经打开的窗口。
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
options |
OpenFloatWindowOptions | 是 | 打开悬浮窗的参数对象。 | 无 | 下列字段 |
options.mode |
FloatWindowMode | 否 | 悬浮模式;业务进入画中画建议使用专用画中画 API。 | Android 为 overlay,iOS/Harmony 为 inApp |
inApp / overlay / pip |
options.focusMode |
FloatWindowFocusMode | 否 | Android 焦点模式;overlay 默认释放输入法焦点。 |
按模式选择 | passthrough / interactive |
options.content |
FloatWindowContent | 是 | 页面或媒体内容。 | 无 | 见下表 |
options.position |
FloatWindowPosition | 否 | 初始坐标。 | 平台默认位置 | { x, y } |
options.size |
FloatWindowSize | 否 | custom 预设使用的自定义尺寸。 |
平台默认尺寸 | { width, height } |
options.sizePreset |
FloatWindowSizePreset | 否 | 尺寸预设。 | medium |
small / medium / large / custom / fullscreen |
options.displayMode |
FloatWindowDisplayMode | 否 | 启用业务展示状态;首次启用时需同时提供 ballSize、panelSize。 |
无 | ball / panel |
options.ballSize |
FloatWindowSize | 否 | 工具球状态使用的尺寸。 | 无 | 有限正数宽高 |
options.panelSize |
FloatWindowSize | 否 | 业务面板状态使用的尺寸。 | 无 | 有限正数宽高 |
options.dragEnabled |
boolean | 否 | 是否允许拖拽。 | true |
true / false |
options.edgeSnap |
boolean | 否 | 拖拽结束后是否吸附边缘。 | false |
true / false |
options.rememberPosition |
boolean | 否 | 是否记忆本次运行期间的最后坐标。 | false |
true / false |
options.keepInScreen |
boolean | 否 | 是否修正到当前可见区域。 | true |
true / false |
options.edgePadding |
number | 否 | 吸附和可见区域修正边距。 | 12 |
大于等于 0 |
options.visible |
boolean | 否 | 打开后是否立即显示。 | true |
true / false |
options.success |
function | 否 | 窗口真实打开后触发。 | 无 | 无 |
options.fail |
function | 否 | 打开失败时触发。 | 无 | 无 |
options.complete |
function | 否 | 调用结束后触发。 | 无 | 无 |
业务展示状态与宿主唤回
displayMode: 'ball' 和 displayMode: 'panel' 共享同一个悬浮页面。首次在 openFloatWindow 中启用时必须同时提供 ballSize、panelSize 和 displayMode;窗口打开后可以使用 setFloatWindowDisplayMode 或 toggleFloatWindowDisplayMode 切换。重复设置当前状态会幂等成功,不重复派发状态变化事件。
onDisplayModeChange 只接收真实状态变化;窗口关闭或页面卸载时调用 offDisplayModeChange。如果配置了 bridgeName,原生还会向 H5 发送 floatWindowDisplayModeChanged,数据包含 previousMode、displayMode、reason 和 timestamp。
bringHostAppToFront 只表示系统接受了宿主唤回请求。Android overlay 可以在用户明确点击订单或客服动作后调用;iOS、Harmony 应用内模式返回“宿主已在前台”;Web、小程序和不支持的模式返回 9015001。插件不会解析页面路径,也不会替宿主保存订单。
内容参数 FloatWindowContent
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
type |
FloatWindowContentType | 是 | 内容来源。 | 无 | url / localAsset / localFile |
value |
string | 是 | HTTP(S) URL、应用资源路径或受支持的应用文件路径;启用远程消息桥或媒体采集时必须使用 HTTPS。 | 无 | 无 |
headers |
object / UTSJSONObject | 否 | 受支持网络媒体的请求头,字段值必须为字符串。 | 无 | 无 |
isVideoStream |
boolean | 否 | 是否为视频流;画中画内容必须为 true。 |
false |
true / false |
liveMode |
string | 否 | PiP 媒体模式;点播声明不能突破实际定位能力。 | auto |
auto / live / vod |
bridgeName |
string | 否 | 启用 H5 双向通信的合法 JavaScript 标识符。 | 无 | 最长 64 字符 |
allowedOrigins |
string[] | 否 | 远程 H5 的精确 HTTPS Origin 白名单。 | 无 | 例如 https://example.com |
webMediaPermissions |
FloatWindowWebMediaPermission[] | 否 | Android/iOS 可信 H5 可请求的媒体能力;空数组拒绝全部采集。 | [] |
camera / microphone |
userAgentSuffix |
string | 否 | 可选的网页 User-Agent 后缀。 | 无 | 无 |
uni-app 可为 headers 传普通对象,uni-app x 使用 UTSJSONObject。localFile 当前对外保证仅用于 Harmony 画中画,并且只接受当前应用自己 files/cache/temp 目录内的普通 MP4。webFileChooser 与 webMediaCapture 是两种不同能力:前者对应标准文件输入,后者对应摄像头和麦克风实时采集。
位置与尺寸
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
position.x |
number | 是 | 水平方向坐标。 | 无 | 无 |
position.y |
number | 是 | 垂直方向坐标。 | 无 | 无 |
size.width |
number | 是 | 自定义宽度。 | 无 | Android 为 px、iOS 为 pt、Harmony 为 vp |
size.height |
number | 是 | 自定义高度。 | 无 | Android 为 px、iOS 为 pt、Harmony 为 vp |
preset |
FloatWindowSizePreset | 是 | 切换预设尺寸。 | 无 | small / medium / large / custom / fullscreen |
画中画参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
enterPictureInPicture.content / openFloatWindow.content |
FloatWindowContent | 否 | 视频来源,isVideoStream 必须为 true;未传时复用当前视频内容,没有可复用内容则失败。 |
当前视频内容 | url / localAsset / localFile |
preparePictureInPicture.content |
FloatWindowContent | 是 | 前台准备的视频来源,isVideoStream 必须为 true;来源类型沿用各平台边界。 |
无 | url / localAsset / localFile(按平台支持) |
startPositionMs |
number | 否 | MP4 / HLS 点播起播位置,单位毫秒。 | 0 |
大于等于 0 |
loop |
boolean | 否 | 是否循环点播媒体;直播流不适用。 | false |
true / false |
progressIntervalMs |
number | 否 | 三端进度事件间隔;非有限数使用默认值,其余限制到范围内。 | 1000 |
250-5000 毫秒 |
autoEnterOnHome |
boolean | 否 | 会话的 Home 自动进入配置;Android/iOS 从 1.0.49 起提供,true 前台默认播放,false 默认暂停;Harmony 准备时不播放,版本限制见模块七。 |
true |
true / false |
positionMs |
number | seek 时是 | 三端点播跳转目标位置,单位毫秒。 | 无 | 有限数且大于等于 0 |
H5 消息参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
event |
string | 是 | 非空业务事件名。 | 无 | 无 |
data |
any | 否 | 可序列化的业务数据。 | null |
无 |
requestId |
string | 否 | 用于关联一组业务请求和响应;插件不会自动等待或解析响应。 | 无 | 无 |
listener |
function | 订阅时是 | H5 发往 App 的持续消息监听器。 | 无 | 无 |
主要返回值
SetMediaPlaybackRequiresUserGestureResult
| 字段 | 类型 | 说明 |
|---|---|---|
required |
boolean | 当前保存的 Android 媒体播放手势要求;默认 true。 |
appliedToCurrentWebView |
boolean | 是否已经应用到当前打开的悬浮网页;false 表示已保存供下一次打开使用。 |
FloatWindowCapabilities
| 字段 | 类型 | 说明 |
|---|---|---|
supported |
boolean | 当前平台是否支持插件的真实原生能力。 |
platform |
string | 当前平台名称。 |
inApp |
boolean | 是否支持应用内悬浮。 |
overlay |
boolean | 是否支持跨应用悬浮。 |
pip |
boolean | 是否支持系统画中画。 |
pipPlaybackControl |
boolean(可选) | 是否支持 PiP 播放、暂停及点播跳转,1.0.47 新增。 |
pipPlaybackState |
boolean(可选) | 是否支持 PiP 播放状态查询,1.0.47 新增。 |
pipProgressEvents |
boolean(可选) | 是否支持 PiP 进度事件,1.0.47 新增。 |
pipAutoEnterOnHome |
boolean(可选) | 当前设备与宿主是否支持 Home 自动进入,按平台和系统动态返回;支持不代表已经进入。Android/iOS 从 1.0.49 起提供,限制见模块七。 |
draggable |
boolean | 是否支持拖拽。 |
resizable |
boolean | 是否支持运行时调整尺寸。 |
edgeSnap |
boolean | 是否支持边缘吸附。 |
positionMemory |
boolean | 是否支持位置记忆。 |
safeAreaCorrection |
boolean | 是否支持安全区域修正。 |
keyboardAvoidance |
boolean | 浮窗输入框是否会随系统键盘避让并在隐藏后恢复。 |
webContent |
boolean | 是否支持网页内容。 |
localAssetContent |
boolean | 是否支持应用资源内容。 |
h5Bridge |
boolean | 是否支持 H5 与 App 双向通信。 |
bridgeOriginAllowlist |
boolean | 是否支持按 HTTPS Origin 限制远程消息桥。 |
webMediaCapture |
boolean | 是否支持可信 H5 摄像头和麦克风采集。 |
hostAppResume |
boolean(可选) | 是否支持悬浮窗请求宿主回到前台;不代表业务路由已配置。 |
webFileChooser |
boolean | 是否支持标准文件输入。 |
requiresOverlayPermission |
boolean | 当前平台使用跨应用 overlay 能力时是否需要系统悬浮权限。 |
requiresCustomBase |
boolean | 是否需要包含插件的自定义基座或原生包。 |
restrictedReason |
string(可选) | 当前平台受限原因。 |
FloatWindowState
| 字段 | 类型 | 说明 |
|---|---|---|
opened |
boolean | 悬浮窗是否已经打开。 |
visible |
boolean | 悬浮窗当前是否可见。 |
mode |
FloatWindowMode | 当前模式。 |
focusMode |
FloatWindowFocusMode(可选) | Android 当前焦点模式。 |
dragEnabled |
boolean | 是否允许拖拽。 |
edgeSnap |
boolean | 是否开启边缘吸附。 |
rememberPosition |
boolean | 是否开启位置记忆。 |
keepInScreen |
boolean | 是否保持在可见区域。 |
edgePadding |
number | 当前边缘留白。 |
position |
FloatWindowPosition | 当前坐标。 |
size |
FloatWindowSize | 当前尺寸。 |
sizePreset |
FloatWindowSizePreset | 当前尺寸预设。 |
displayMode |
FloatWindowDisplayMode(可选) | 当前业务展示状态;未启用球/面板模式时为空。 |
ballSize |
FloatWindowSize(可选) | 工具球状态尺寸。 |
panelSize |
FloatWindowSize(可选) | 业务面板状态尺寸。 |
content |
FloatWindowContent | null | 当前内容;未打开时可为空。 |
OverlayPermissionResult
| 字段 | 类型 | 说明 |
|---|---|---|
platform |
string | 当前平台。 |
granted |
boolean | 是否已经获得 Android 跨应用悬浮权限。 |
requiresOverlayPermission |
boolean | 当前平台是否需要该权限。 |
canOpenSettings |
boolean | 是否可以打开系统设置页。 |
settingsUri |
string(可选) | Android 可用的设置页地址。 |
packageName |
string(可选) | Android 应用包名。 |
restrictedReason |
string(可选) | 平台限制说明。 |
FloatWindowDiagnosticsResult
| 字段 | 类型 | 说明 |
|---|---|---|
platform |
string | 当前平台。 |
state |
FloatWindowState | 当前悬浮窗运行态。 |
overlayPermission |
OverlayPermissionResult | Android 跨应用悬浮权限快照。 |
webViewReady |
boolean | 网页容器是否已经就绪。 |
windowAttached |
boolean | 原生窗口是否已经附着。 |
layoutReady |
boolean | 布局是否已经可用。 |
listenerStatus |
FloatWindowListenerStatus | 拖拽、点击和内容监听器注册状态。 |
bridgeEnabled |
boolean | 当前内容是否启用了消息桥。 |
bridgeReady |
boolean | 当前消息桥是否可以收发消息。 |
bridgeName |
string | null | 当前桥对象名称。 |
currentOrigin |
string | null | 当前页面 Origin。 |
allowedOrigins |
string[] | 当前生效的远程 HTTPS Origin 白名单。 |
webMediaPermissions |
string[] | 当前允许的网页媒体能力。 |
mediaPermissionPending |
boolean | 当前是否存在待处理的网页媒体权限请求。 |
cameraPermissionGranted |
boolean | App 是否获得摄像头系统权限。 |
microphonePermissionGranted |
boolean | App 是否获得麦克风系统权限。 |
lastMediaError |
string | null | 最近媒体错误摘要。 |
lastBridgeError |
string | null | 最近桥接错误摘要。 |
requiresCustomBase |
boolean | 是否需要包含插件的自定义基座或原生包。 |
sdkInt |
number(可选) | Android 系统 API 级别。 |
restrictedReason |
string(可选) | 平台限制说明。 |
PictureInPicturePlaybackState
| 字段 | 类型 | 说明 |
|---|---|---|
prepared |
boolean | 本会话媒体、视图和系统画中画是否已经准备;不等于已经进入。 |
active |
boolean | 系统是否已确认画中画窗口活动。 |
autoEnterOnHome |
boolean | 本会话请求的自动进入配置;暂停、播放完成或系统条件可能暂时撤销实际资格,该字段不表示已经进入。 |
playerState |
string | 当前播放器状态。 |
sourceType |
FloatWindowContentType | null | 当前媒体来源类型。 |
isLive |
boolean | 当前媒体是否为直播流。 |
playing |
boolean | 当前媒体是否正在播放。 |
seekable |
boolean | 当前媒体是否允许跳转。 |
positionMs |
number | 当前播放位置,单位毫秒。 |
durationMs |
number | 当前媒体时长,直播或未知时为 0。 |
loop |
boolean | 是否循环点播媒体。 |
progressIntervalMs |
number | 进度事件间隔,单位毫秒。 |
H5 消息返回值
| 字段 | 类型 | 说明 |
|---|---|---|
delivered |
boolean | App 消息是否已经交给当前 H5 页面。 |
bytes |
number | 序列化后消息的 UTF-8 字节数。 |
targetOrigin |
string | null | 本次派发的目标 Origin。 |
event |
string | H5 发往 App 的业务事件名。 |
data |
any | H5 发往 App 的业务数据。 |
requestId |
string | null | 请求关联标识。 |
sourceOrigin |
string | null | 消息来源 Origin。 |
isMainFrame |
boolean | null | 是否来自主页面。 |
timestamp |
number | App 接收消息的毫秒时间戳。 |
事件
悬浮窗事件
| 监听 API | 返回内容 | 取消监听 |
|---|---|---|
onMove |
拖拽后的 x / y / timestamp。 |
offMove |
onClick |
点击位置和时间。 | offClick |
onContentEvent |
页面加载或系统画中画内容事件。 | offContentEvent |
onDisplayModeChange |
工具球/业务面板实际变化的 previousMode / displayMode / reason / timestamp。 |
offDisplayModeChange |
onH5Message |
H5 发往 App 的结构化业务消息。 | offH5Message |
页面卸载时应调用对应的 off... API,避免重复订阅。
Harmony 页面事件
| 事件名 | 说明 |
|---|---|
controllerAttached |
网页控制器已经和悬浮内容关联。 |
pageBegin |
主页面开始加载。 |
pageEnd |
主页面加载完成。 |
pageError |
主页面加载失败。 |
系统画中画事件
| 事件名 | 说明 |
|---|---|
pipPreparing |
正在准备媒体和系统画中画;Android/iOS 从 1.0.49 起提供。 |
pipPrepared |
媒体已准备,可继续控制或按平台条件等待 Home;不表示系统已进入。 |
pipStarted |
系统已真实确认进入画中画。 |
pipPlaying |
视频正在播放。 |
pipPaused |
视频已暂停。 |
pipProgress |
返回播放状态与进度快照;直播时长可能为 0。 |
pipSeeked |
点播媒体已完成跳转。 |
pipRestored |
系统发起返回主应用的恢复流程;课程续播以 pipStopped 的快照为准。 |
pipStopped |
系统画中画已关闭;payload.data 为 { reason, snapshot },请按原因决定是否续播。 |
pipError |
系统画中画准备、播放或控制失败。 |
错误码说明
错误对象errSubject为lizhao-float-window;失败请保留errCode、errMsg和可取得的details。
| 错误码 | 含义 | 常见场景 |
|---|---|---|
9015001 |
当前平台或能力不支持。 | Web、小程序调用原生能力,或调用平台专属 API。 |
9015002 |
参数或内容不合法。 | 参数为空,URL、路径或请求头格式错误。 |
9015003 |
Android 跨应用悬浮权限未授予。 | 打开 overlay 前没有完成系统授权。 |
9015004 |
悬浮窗尚未打开。 | 在打开前调用更新、显隐、位置等 API。 |
9015005 |
当前操作状态冲突。 | 重复打开、画中画正在处理,或当前状态不允许取消、播放、暂停、跳转。 |
9015006 |
当前平台不允许请求的模式。 | iOS、Harmony 请求 Android 跨应用悬浮。 |
9015007 |
媒体来源、格式或当前媒体控制不支持。 | 画中画内容无效、直播流跳转、媒体不可播放。 |
9015008 |
原生系统操作失败。 | 窗口、播放器、媒体准备/定位或系统画中画调用失败;需结合 errMsg 和真实状态排查。 |
9015009 |
当前操作忙。 | 画中画正在处理其他操作。 |
9015010 |
当前内容容器或消息桥不可用。 | 网页容器尚未创建或已经释放。 |
9015011 |
可信 Web 配置不合法。 | 桥名、Origin 或 webMediaPermissions 非法。 |
9015012 |
当前页面未获得桥接授权。 | 没有启用桥,或页面不在获批范围。 |
9015013 |
H5 消息桥尚未就绪。 | 页面未加载完成或已经离开可信 Origin。 |
9015014 |
H5 消息格式无效。 | event 为空或数据无法序列化。 |
9015015 |
H5 消息过大。 | UTF-8 序列化后超过 256 KB。 |
9015016 |
App 向 H5 派发失败。 | 原生派发过程失败。 |
注意事项
宿主与平台
| 平台 | 支持情况 | 主要能力 | 是否需要包含插件的原生包 |
|---|---|---|---|
| App Android | 支持 | 应用内悬浮、球/面板切换、跨应用悬浮、宿主唤回、系统画中画、H5 通信、文件选择、摄像头和麦克风。 | 需要 |
| App iOS | 部分支持 | 应用内悬浮、球/面板切换、系统画中画、H5 通信、系统文件选择、摄像头和麦克风;不支持跨应用悬浮。 | 需要 |
| App Harmony | 部分支持 | 应用内悬浮、球/面板切换、系统画中画、H5 通信、系统文件选择、本地及网络视频;不支持跨应用悬浮和网页摄像头/麦克风采集。 | 需要 |
| Web/H5 | 不支持 | 可查询能力并显示不支持提示,不创建悬浮窗。 | 不需要 |
| 微信小程序 | 不支持 | 可查询能力并显示不支持提示,不创建悬浮窗。 | 不需要 |
| 支付宝小程序 | 不支持 | 可查询能力并显示不支持提示,不创建悬浮窗。 | 不需要 |
同一套 App 业务代码可以先调用 getCapabilities(),再根据 inApp、overlay、pip、h5Bridge、webMediaCapture 等字段决定是否显示对应入口。
使用边界
平台差异。 iOS/Harmony不支持普通跨应用悬浮;Harmony不支持网页摄像头/麦克风实时采集。文件选择与getUserMedia是不同能力,须分别查询。fullscreen只覆盖应用可用区域。
H5授权。 远程桥只允许精确HTTPS Origin,消息event非空,序列化UTF-8单条最大256KB;消息桥未就绪返回真实失败。摄像头/麦克风需可信来源、webMediaPermissions及系统权限;插件不提供任意JavaScript执行能力。Android自动播放仍受内容、系统与用户手势影响。
画中画归属。 Android/iOS可用requestId追踪首个事件前的请求;expectedRequestId与expectedSessionId互斥。保存事件/真实状态再按归属取消准备或退出;成功提交不代替系统实际状态。prepare/Home自动进入、autoplay/muted及Harmony来源/鉴权限制见本文后续完整说明,不推定三端相同。
退出业务。 对持续事件调用对应off方法,结束业务后关闭窗口或按归属退出画中画。诊断可能包含Origin、权限与错误摘要,分享前复核。
首次接入或原生代码、依赖与构建配置变化后,须重新制作并安装匹配的自定义基座或正式包;仅修改普通页面、样式或文档,无需重打原生基座。
完整平台、权限与使用说明
常见问题
第一次接入应该先测试什么
先调用 getCapabilities(),再用 inApp + localAsset + small 打开最小悬浮窗。该流程不需要 Android 跨应用悬浮权限,最适合检查插件是否已经正确导入,以及当前安装包是否包含插件能力。
Android 全局悬浮窗为什么打不开或返回 9015003
先调用 checkOverlayPermission()。未授权时,让使用者点击按钮进入系统设置页;返回 App 后重新检查,只有 granted=true 才打开 overlay。插件不会静默开启系统权限。
iOS 或 Harmony 能否在离开 App 后继续显示普通悬浮窗
不能。两者支持应用内悬浮和系统允许的视频画中画,不支持 Android 式跨应用普通悬浮窗。请根据 capabilities.overlay 和 capabilities.pip 决定是否展示入口。
Android 悬浮页能点击,但输入框为什么不弹键盘
overlay 默认使用 passthrough,用于避免影响其他 App 的输入。悬浮页需要输入时调用 updateFloatWindow({ focusMode: 'interactive' });输入完成后可切回 passthrough。inApp 默认允许输入。插件支持键盘自动避让,底部输入框获得焦点后会平稳移动到键盘上方,键盘关闭后恢复原有页面大小;可通过 keyboardAvoidance 判断当前平台是否支持。
fullscreen 为什么没有覆盖状态栏、刘海或系统导航区域
fullscreen 的含义是铺满当前应用的安全可用区域,并随窗口尺寸变化更新,不是覆盖系统界面的物理屏幕全屏。全屏状态下位置固定,也不响应拖拽。
系统已经允许摄像头和麦克风,H5 为什么仍无法获取设备
系统权限只是其中一层。当前 content 还必须配置最终页面的精确 HTTPS allowedOrigins,并在 webMediaPermissions 中列出页面实际请求的 camera、microphone。空配置按安全默认值拒绝全部媒体采集;iframe 还需要相应的 allow 属性。
H5 与 App 消息为什么返回 9015012、9015013 或 9015015
9015012:当前页面没有启用桥,或页面已离开允许的 Origin。9015013:页面还没有加载完成,消息桥尚未就绪。9015015:消息序列化后超过 256 KB。
同时检查 bridgeName 是否为合法标识符、远程页面是否使用精确 HTTPS Origin、event 是否为非空字符串。
Android H5 自动播放为什么仍被阻止
先在打开悬浮网页前调用 setMediaPlaybackRequiresUserGesture({ required: false })。如果之前的 play() 已经被浏览器拒绝,设置成功后仍要由 H5 重新发起播放。该设置只支持 Android,也不负责摄像头或麦克风授权。
网页或视频为什么无法进入系统画中画
画中画只用于真实视频。先确认 capabilities.pip=true,并在内容中传入 isVideoStream: true。Android 还要求 Android 8.0 及以上且当前 App 页面允许画中画;插件已声明普通页面与 Vapor 页面的支持,更新该配置后须重新制作并安装 Android 自定义基座或正式安装包。普通网页和业务卡片应使用悬浮窗模式。
按 Home 没进入或返回 9015008 怎么排查
9015008 可能来自系统拒绝、原生异常或媒体准备/定位失败,单凭错误码不能确定原因。按以下顺序检查:
- 确认版本与能力:1.0.48 的 Home 准备仅支持 Harmony;Android/iOS 从 1.0.49 起提供上述能力,要求匹配本版本原生插件的基座。自动进入分别要求 Android 12+、iOS 14.2+ 及设备/系统允许。
- 在 App 前台准备真实可播放视频,Android/iOS 保留可见预览并保持播放,等待准备成功后再按 Home;首次初始化放到
onHide会错过前台准备过程,不能用此时补调进入来代替。 - 检查系统 PiP 设置、
autoEnterOnHome配置和播放状态。暂停或播完会撤销实际自动资格;能力为true、准备成功都不等于active=true。 - 保留
fail返回的errCode / errMsg、系统版本和getPictureInPicturePlaybackState快照,结合pipError排查;不要只看到准备成功就向业务报告进入成功。
localFile 可以传任意本地路径吗
不可以。当前对外保证中,localFile 只支持 Harmony 画中画,并且文件必须是当前应用自己目录中的 MP4。随应用发布的视频使用 localAsset;任意系统绝对路径、目录、符号链接和跨应用文件均不支持。
文件选择和摄像头实时采集是同一个能力吗
不是。webFileChooser 对应标准 <input type="file">;webMediaCapture 对应网页实时使用摄像头和麦克风。应分别读取能力并按业务显示入口。
升级插件后为什么行为仍和旧安装包一致
该插件包含原生能力。首次接入,或更新说明明确包含原生能力变更时,需要重新制作并安装对应平台的自定义基座或正式安装包;纯文档和页面资源更新不需要重新制作。
注意事项
- 远程 H5 只允许精确 HTTPS Origin;消息必须包含非空
event,单条最大 256 KB,插件不提供任意 JavaScript 执行能力。 - 网页媒体权限按最小需要配置;长期 Token、密钥和生产凭据不得写入页面、README 或代码仓库。
- 页面卸载时应取消持续监听,业务结束时应关闭悬浮窗或退出画中画,避免重复回调和资源占用。
- 诊断结果可能包含当前页面 Origin、权限状态和最近错误摘要,对外提供前应先检查内容。
- App 端首次接入,或更新说明明确包含原生能力变更时,需要重新制作并安装对应平台的自定义基座或正式安装包;纯文档和页面资源更新不需要重新制作。
作者系列 UTS 插件
以下为作者已上架的 UTS 插件,详情见各市场页面或作者主页。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-app-keepalive |
应用保活、唤醒、自愈与报告 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列、倍速与事件 | 查看插件 |
lizhao-ble |
BLE 扫描、连接、读写、通知与自动重连 | 查看插件 |
lizhao-call-kit |
电话、短信、通讯录原生能力 | 查看插件 |
lizhao-camera-pro |
原生相机、拍照录像、水印与媒体保存 | 查看插件 |
lizhao-cast-screen |
DLNA 投屏、AirPlay 路由入口 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-device-id |
设备标识、隐私策略与诊断 | 查看插件 |
lizhao-doc-corrector |
文档扫描、矫正、增强与识别 | 查看插件 |
lizhao-emu-detect |
模拟器环境检测、风险评分与证据 | 查看插件 |
lizhao-float-window |
悬浮窗、画中画、权限与诊断 | 查看插件 |
lizhao-gallery-pro |
相册媒体分页、筛选、缩略图与导出 | 查看插件 |
lizhao-hce-card |
NFC 虚拟卡、APDU 交互与 NDEF 标签模拟 | 查看插件 |
lizhao-health |
健康数据授权、查询、统计与写入 | 查看插件 |
lizhao-http-server |
本地 HTTP 服务、文件传输与实时通信 | 查看插件 |
lizhao-icon-pro |
SVG 图标组件、多主题与缓存 | 查看插件 |
lizhao-id-photo |
证件照制作、尺寸换算、换底色与模板换装 | 查看插件 |
lizhao-img-eraser |
图片去水印、局部修复与原生编辑器 | 查看插件 |
lizhao-live-activity |
实时活动、系统胶囊与普通通知降级 | 查看插件 |
lizhao-nfc-pro |
NFC 标签读写、NDEF、IsoDep 与诊断 | 查看插件 |
lizhao-notify-pro |
本地通知、点击动作、进度与定时提醒 | 查看插件 |
lizhao-novel-reader |
原生小说阅读、仿真翻页与段落评论 | 查看插件 |
lizhao-office-view |
Office 与 PDF 文件预览、进度与缓存管理 | 查看插件 |
lizhao-pdf-pro |
PDF 阅读、签批、真实写回与页面处理 | 查看插件 |
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-serial-port |
路径串口、USB 串口、多会话收发与诊断 | 查看插件 |
lizhao-share-plus |
系统分享、远程文件下载后分享 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移、备份与诊断 | 查看插件 |
lizhao-sse-pro |
SSE、Line、JSONL 与 Raw 流式请求 | 查看插件 |
lizhao-tcp-pro |
TCP 客户端、服务端、多连接与诊断 | 查看插件 |
lizhao-usb-storage |
U 盘、移动硬盘文件浏览、读写与批量复制 | 查看插件 |
lizhao-video-editor |
视频裁剪、压缩、取帧与 FFmpeg/FFprobe | 查看插件 |
lizhao-video-feed |
短视频上下滑、短剧选集与分页加载 | 查看插件 |
lizhao-video-player |
原生视频播放器、清晰度与播放交互 | 查看插件 |
lizhao-video-thumb |
视频封面、批量取帧与 Base64 返回 | 查看插件 |
lizhao-vpn-pro |
企业 VPN、IKEv2、安全接入与脱敏诊断 | 查看插件 |
lizhao-wechat-kit |
微信登录、分享、支付、小程序与客服 | 查看插件 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 6486
赞赏 5
下载 12731195
赞赏 1959
赞赏
京公网安备:11010802035340号