更新记录
1.0.16(2026-07-08)
- 将 uni-app / uni-app x 示例默认视频源从会跳转到 HTTPS 的
media.w3.org地址换成真机验证过的普通 HTTP MP4http://vjs.zencdn.net/v/oceans.mp4,并补充Macast(yunxi)与 Windows 自带yunxi设备的 716 排查说明,避免把 Macast 接收器误选成 Windows Digital Media Renderer。 - 修复 iOS 不使用内置面板、直接点击设备或业务自定义面板选择设备时反馈不明显的问题:示例页新增
CONNECT_DEVICE_CLICK、CONNECT_DEVICE_BEFORE_NATIVE_CALL、CONNECT_DEVICE_AFTER_NATIVE_CALL日志,并在连接成功后刷新诊断与设备状态。 - 加固 uni-app / uni-app x 示例设备列表刷新:
getDiscoveredDevices()短暂返回空数组时保留已发现设备,避免deviceListChange已发现设备后列表又被空查询清空。 - 加固 iOS 连接事件同步:DLNA 连接成功后额外派发包含 connected 状态的
deviceListChange,便于客户自定义 UI 只监听设备列表事件时也能更新“已连接”状态。 - 修复 iOS 点击“开始投屏”前执行媒体预检时,
CastMediaInspection强类型 success 回调被 Swift 桥接层误强转为(Any) -> Void导致SIGABRT闪退的问题。 - 强化 iOS 回调分发:
CastFail、CastSupportBundle、CastMediaInspection统一走强类型直接回调,避免success / fail / complete在不同 API 结果类型之间复用 any 回调桥引发原生崩溃。 - 加固 iOS 连接
Macast(yunxi)/ Windows DMR 后开始投屏返回HTTP 500的兼容风险:DLNA DIDL-Lite 元数据改为与 Android 对齐的parentID="-1"与protocolInfo="http-get:*:<mime>:*",并增强 SOAP 错误日志输出真实 action 与 UPnP fault,便于区分接收端资源不可访问和协议元数据不兼容。 - 加固 iOS
SetAVTransportURI对 Macast 0.7 / CherryPy 旧接收端的兼容性:SOAP POST 使用URLSession.uploadTask显式发送 UTF-8 请求体,并补齐Content-Length、Connection: close和Accept:*/*,避免接收端将dataTask + httpBody识别为空 body;在SetAVTransportURI收到 5xx 时短延迟重试一次;HTML 500 响应日志截断提高到 4096 字符,便于客户复制 Macast traceback。 - 继续加固 iOS
SetAVTransportURI对Macast(yunxi)与 Windows Digital Media Renderer 的控制请求兼容:解析controlURL时保留?control=查询串,避免 Windows DMR 因udhisapi.dll%3Fcontrol=...返回Invalid Header;普通 HTTP SOAP POST 改为原始 HTTP/1.1 POST 写入 header、空行和 UTF-8 body,避免 Macast 0.7 继续读到空 XML body。 - 加固 iOS 连接 Windows Digital Media Renderer 后点击“投屏当前媒体”返回
UPnP 716 Resource not found的兼容性:主路径继续使用protocolInfo="http-get:*:<mime>:*",仅在SetAVTransportURI明确返回 716 时自动尝试 Windows DMR 备用元数据DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000和空元数据,减少接收端把可访问普通 HTTP MP4 误判为资源不可用的概率。 - 补充 uni-app / uni-app x 示例日志:新增
START_CAST_CLICK、START_CAST_BEFORE_NATIVE_CALL、START_CAST_AFTER_NATIVE_CALL、CAST_MEDIA_INSPECTION_BEFORE_NATIVE_CALL、CAST_MEDIA_INSPECTION_AFTER_NATIVE_CALL,便于客户复现“连接后开始投屏”时定位按钮链路。 - 升级发布版本到
1.0.16,同步package.json、商业就绪状态和 Android/iOS/Harmony/API 运行诊断版本;iOS 真机诊断version必须显示1.0.16才代表同时包含自定义 UI 连接反馈、列表保留和开始投屏闪退修复。
1.0.15(2026-07-06)
- 修复 iOS 自动 SSDP 已发现设备但示例页设备列表仍显示为空的问题:
deviceListChange事件 payload 会优先同步到 uni-app / uni-app x 示例页设备列表,不再被后续空查询覆盖。 - 加固 iOS 运行态设备快照:
getDiscoveredDevices/getCastDiagnostics从 native 快照同步到空数组时,会保留 UTS 层已通过deviceListChange写入的真实 DLNA 设备,避免诊断仍显示deviceCount:0。 - 升级发布版本到
1.0.15,同步package.json、商业就绪状态和 Android/iOS/Harmony/API 运行诊断版本,便于客户确认已包含本轮设备列表显示修复。 - 本版本仍属于 iOS 已授权 Multicast 自动 SSDP 构建,客户需要使用包含
com.apple.developer.networking.multicast的 provisioning profile 重新打 iOS 自定义基座。
1.0.14(2026-07-06)
- 单独升级已获 Apple Multicast Networking 权限客户的 iOS 自动 SSDP 搜索版本:包版本、商业就绪状态和 Android/iOS/Harmony/API 运行诊断版本统一到
1.0.14。 - 开启 iOS 自动 SSDP 搜索:
iosAutomaticSsdpEnabledByDefault改为true,在未传manualDeviceDescriptionUrl时会直接进入CastScreenNative.startDiscovery,不再返回ios-multicast-entitlement-required保护提示。 - iOS
UTS.entitlements内置com.apple.developer.networking.multicast,用于客户已开通 App ID、重新生成 provisioning profile 并重新打 iOS 自定义基座后的自动搜索验收。 - 更新 README 和发布守卫,明确
1.0.14适用于描述文件已包含 Multicast Networking 的构建;未获批客户仍应使用手动device.xml/description.xml链路或不声明 multicast 的保护构建。
平台兼容性
uni-app(5.07)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
uni-app x(5.07)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ |
lizhao-cast-screen
lizhao-cast-screen 是一个面向 uni-app / uni-app x 的商业级 UTS 媒体投屏插件。插件最大特色是内置暗黑科技风投屏面板:底部近全屏呈现、深浅色主题、设备扫描、选集、清晰度、投屏成功后的进度控制、音量、快进快退和断开控制都在插件内部完成;业务也可以通过事件完全自定义界面。
功能特色
- Android 使用 DLNA/UPnP 实现媒体投屏:支持 SSDP 搜索、设备去重、连接、播放普通
httpMP4 / https 远程视频 URL,也支持image/jpeg等远程图片 URL 投屏;视频保留暂停、恢复、seek、音量、停止和断开,图片不伪造视频控制。 - iOS 新增 DLNA/UPnP DMR 媒体投屏:支持 SSDP 搜索、手动
device.xml发现、AVTransport / RenderingControlSOAP 控制、远程视频/图片投屏、视频暂停、恢复、seek、音量、停止和进度快照;同时保留系统 AirPlay 路由入口,不做私有 AirPlay 反射,图片请走 DLNA 设备。 - Harmony 新增 DLNA/UPnP DMR 媒体投屏:支持 SSDP 搜索、手动
device.xml发现、AVTransport / RenderingControlSOAP 控制、远程视频/图片投屏、视频暂停、恢复、seek、音量、停止、进度快照、诊断包和媒体源预检;内置面板优先使用 Android 风格 ArkUI 近全屏底部 Sheet,承接搜索、选设备、投屏、3D 遥控控制台、音量加减、快退/快进和胶囊选集/清晰度,UIContext 不可用时降级到系统 ActionSheet。 - iOS 内置底部近全屏面板新增
DLNA 设备 / AirPlay 路由分段切换:DLNA 页提供设备列表、扫描入口、投屏当前媒体、暂停/恢复、停止和断开控制;AirPlay 页保留AVRoutePickerView系统路由入口,AirPlay 设备选择仍交给系统完成。 - 内置面板状态基础矩阵覆盖搜索中、设备列表、连接中、已连接、投屏中、已暂停、已停止、无设备、失败可重试,并额外支持投屏请求中加载态;面板只展示真实状态,不伪造设备发现、连接或投屏成功;Android 点击“投屏”后会立即显示“投屏中...”并禁用重复点击,投屏成功后主按钮切换为“暂停”,暂停后显示“播放”,停止后显示“继续投屏”;进度条只在真实投屏媒体建立且有明确时长后显示,Android 投屏成功后通过
GetPositionInfo异步轮询电视端真实进度,轮询期间只轻量刷新当前时间和进度条,暂停/播放/停止只轻量刷新状态文案和按钮,避免整面板重建造成界面闪动;Android/iOS 支持拖拽后触发真实seekCast。 - 连接设备后自动切换为紧凑产品级控制台和暗黑科技风微光媒体控制台,提供玻璃卡片、发光控制盘、选集、清晰度、顶部单图标主题按钮、快退 15 秒、快进 15 秒、音量加减、投屏当前媒体和原地刷新。
- 标题右侧扫描设备入口默认可用,不再展示“使用业务自定义界面”按钮;业务自定义入口请使用
showCastPanel({ useBuiltinUI: false })与事件回调。 - 支持
dark / light / auto主题。auto跟随系统,dark适合影音投屏场景,light适合浅色业务页面。 - 提供
getCastDiagnostics、exportCastSupportBundle、inspectCastMediaSource,方便线上诊断设备、媒体源和投屏状态。
支持平台
| 平台 | 是否支持 | 说明 |
|---|---|---|
| App Android | 支持 | 真实 DLNA DMR 媒体投屏,需要自定义基座;Android 9/API 28+ 已配置 cleartext 边界。 |
| App iOS | 支持 | 真实 DLNA/UPnP DMR 媒体投屏 + AirPlay 系统路由入口,需要自定义基座。 |
| App Harmony | 支持 | 真实 DLNA/UPnP DMR 媒体投屏,需要自定义基座;内置面板优先使用 ArkUI 底部 Sheet,必要时降级到系统 ActionSheet。 |
| Web/H5 | 降级 | 返回 supported:false,不伪造设备发现。 |
| 微信小程序 | 降级 | 返回 supported:false,可展示业务入口事件。 |
| 支付宝小程序 | 降级 | 返回 supported:false,可展示业务入口事件。 |
插件市场平台标记说明
插件市场平台标记会按 uni-app / uni-app x 跨端可安装和可调用能力展示;真实投屏能力仍按“真实投屏能力”标记和说明:App Android / App iOS / App Harmony 支持原生 DLNA/UPnP(iOS 额外提供 AirPlay 系统路由入口),Web/H5、小程序和快应用只提供统一 API 与降级入口。源码中保留 app-harmony、web、mp-weixin、mp-alipay 平台目录,是为了让业务可以获得一致 API 和 useBuiltinUI:false 自定义入口;其中 Harmony 端具备真实 DLNA 投屏能力,Web/H5 与小程序端不代表可以真实发现设备或投屏成功。
安装说明
- 将插件放入项目的
uni_modules/lizhao-cast-screen目录。 - 页面中只从插件根目录导入,不要导入
utssdk子路径。 - App Android / App iOS / App Harmony 使用真实原生能力时,需要重新制作并安装自定义基座。
- H5、小程序可以调用同名 API 获取降级能力,但不要在 UI 中声明真实投屏成功。
import * as CastScreen from '@/uni_modules/lizhao-cast-screen'
如只需要类型,也可以从根入口使用公开类型;插件内部 utssdk/api.uts 是 API 汇总实现文件,业务页面仍应从插件根目录导入。
示例代码位置
插件内部已内置完整演示页面:
uni_modules/lizhao-cast-screen/example/uniapp/castScreen.vue
uni_modules/lizhao-cast-screen/example/uniappx/index.uvue
使用方式:
- uni-app 项目可参考
uni_modules/lizhao-cast-screen/example/uniapp/castScreen.vue,复制到项目页面目录,例如uni_modules/lizhao-cast-screen/example/uniapp/castScreen.vue。 - uni-app x 项目可参考
uni_modules/lizhao-cast-screen/example/uniappx/index.uvue,页面仍只从插件根目录导入 API 和类型。 - 在
pages.json中增加页面路由。 - App 端真实投屏能力需要重新运行到自定义基座;如果本轮只复制页面、不改插件原生代码,可以先运行页面验证 UI 与 API 调用。
{
"pages": [
{
"path": "uni_modules/lizhao-cast-screen/example/uniapp/castScreen",
"style": {
"navigationBarTitleText": "投屏控制演示"
}
}
]
}
示例页包含:内置面板、业务自定义面板、扫描设备、连接设备、开始投屏、投屏图片、暂停/恢复、seek、音量、停止、诊断包和媒体源预检。uni-app 示例位于 uni_modules/lizhao-cast-screen/example/uniapp/castScreen.vue,uni-app x 示例位于 uni_modules/lizhao-cast-screen/example/uniappx/index.uvue,便于用户安装插件后直接参考。
快速开始
import * as CastScreen from '@/uni_modules/lizhao-cast-screen'
CastScreen.initCast({
debug: true,
autoStartDiscovery: false,
success() {
console.log('投屏插件初始化完成')
},
fail(err) {
console.log('投屏插件初始化失败', err)
}
})
const capabilities = CastScreen.getCastCapabilities()
console.log('投屏能力', capabilities)
展示内置投屏面板
CastScreen.showCastPanel({
title: '投屏到电视',
subtitle: '请选择同一 Wi-Fi 下的设备',
theme: 'auto',
media: {
url: 'http://vjs.zencdn.net/v/oceans.mp4',
title: 'Oceans HTTP MP4',
mimeType: 'video/mp4'
},
episodes: [
{
id: 'ep-1',
title: '第 1 集 Sintel 预告',
url: 'http://vjs.zencdn.net/v/oceans.mp4',
mimeType: 'video/mp4',
episodeIndex: 1
},
{
id: 'ep-2',
title: '第 2 集 Big Buck Bunny',
url: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
mimeType: 'video/mp4',
episodeIndex: 2
}
],
qualities: [
{ id: 'auto', label: '自动', selected: true },
{ id: '720p', label: '720P', url: 'http://vjs.zencdn.net/v/oceans.mp4', mimeType: 'video/mp4' },
{ id: '1080p', label: '1080P' }
],
showThemeToggle: true,
success() {
console.log('内置投屏面板已展示')
}
})
浅色主题示例:
CastScreen.showCastPanel({
theme: 'light',
title: '投屏到会议屏',
subtitle: '浅色业务页面推荐使用 light 主题'
})
选集或清晰度项带 url 时,用户点击对应项会触发真实 startCast 流程;如果不带 url,插件只派发 customAction 给业务层,不会伪造投屏成功。
投屏图片示例
CastScreen.startCast({
media: {
// 图片必须是电视/盒子可直接访问的远程 URL,本地相册路径需要先上传或转换为可访问地址。
url: 'https://media.w3.org/2010/05/sintel/poster.png',
title: '投屏图片示例',
mediaKind: 'image',
mimeType: 'image/jpeg'
},
success() {
console.log('图片投屏已发送到 DLNA 设备')
},
fail(err) {
console.log('图片投屏失败', err)
}
})
图片投屏在 DLNA 元数据中使用 object.item.imageItem.photo;视频仍使用 object.item.videoItem。图片没有播放时长,不会触发视频进度、暂停、恢复或 seek 控制。
业务自定义界面示例
CastScreen.onCastEvent('*', (event) => {
if (event.name == 'customAction') {
console.log('业务自定义事件', event.payload)
}
if (event.name == 'deviceListChange') {
console.log('设备列表变化', event.payload)
}
})
CastScreen.showCastPanel({
useBuiltinUI: false,
title: '业务自定义入口',
showCustomAction: true,
customActionText: '打开业务投屏弹窗'
})
useBuiltinUI:false 在降级端也可以触发业务入口;但如果能力矩阵返回 supported:false,请在业务 UI 中提示“当前平台暂不支持真实投屏”,不要伪造设备发现或投屏成功。
iOS 真机建议业务自定义入口同时传入 showCustomAction:true 或 customActionText,避免可选布尔字段在桥接默认值中与内置面板调用混淆。
API 列表
| API | 说明 |
|---|---|
initCast |
初始化投屏运行时。 |
getCastCapabilities |
获取平台能力矩阵。 |
startDiscovery |
开始搜索设备。 |
stopDiscovery |
停止搜索设备。 |
getDiscoveredDevices |
获取当前缓存设备列表。 |
showCastPanel |
展示内置底部近全屏面板或业务自定义入口。 |
hideCastPanel |
隐藏内置面板。 |
connectDevice |
连接指定投屏设备。 |
disconnectDevice |
断开当前设备。 |
startCast |
开始投屏媒体 URL。 |
pauseCast |
暂停远端播放。 |
resumeCast |
恢复远端播放。 |
seekCast |
跳转远端播放进度。 |
setCastVolume |
设置远端音量。 |
stopCast |
停止远端播放,保留当前设备和媒体以便继续投屏。 |
getCastSessionState |
获取会话状态。 |
getCastDiagnostics |
获取运行诊断快照。 |
exportCastSupportBundle |
导出售后诊断包。 |
inspectCastMediaSource |
预检媒体源是否适合投屏。 |
onCastEvent |
监听投屏事件。 |
offCastEvent |
移除投屏事件监听。 |
完整 API 行为速查
| API | 支持平台 | 返回/回调 | 失败或降级说明 |
|---|---|---|---|
initCast(options) |
全平台 | 回调 | 不支持平台返回 9030001。 |
getCastCapabilities(options?) |
全平台 | CastCapabilities |
降级端返回 supported:false。 |
startDiscovery(options) |
Android/iOS/Harmony | 回调 | Android/iOS/Harmony 搜索 DLNA DMR;iOS 仍保留 AirPlay 系统路由入口;Web/H5 与小程序失败。 |
stopDiscovery(options?) |
全平台 | 回调 | 降级端安全收口。 |
getDiscoveredDevices(options?) |
全平台 | Array<CastDevice> |
无设备返回空数组,不伪造设备。 |
showCastPanel(options?) |
Android/iOS/Harmony | 回调 | Android/iOS 展示原生面板;Harmony 展示 ArkUI 底部 Sheet 内置面板;useBuiltinUI:false 可走业务入口。 |
hideCastPanel(options?) |
全平台 | 回调 | 面板不存在时安全收口。 |
connectDevice(options) |
Android/iOS/Harmony | 回调 | 设备不存在或平台不支持返回失败。 |
disconnectDevice(options?) |
Android/iOS/Harmony | 回调 | 可选 stopRemote 停止远端播放。 |
startCast(options) |
Android/iOS/Harmony | 回调 | 只支持电视可访问的远程视频/图片 URL。 |
pauseCast(options?) |
Android/iOS/Harmony | 回调 | 当前无会话或平台不支持返回失败。 |
resumeCast(options?) |
Android/iOS/Harmony | 回调 | 当前无会话或平台不支持返回失败。 |
seekCast(options) |
Android/iOS/Harmony | 回调 | position 小于 0 返回参数错误。 |
setCastVolume(options) |
Android/iOS/Harmony | 回调 | volume 范围为 0-1。 |
stopCast(options?) |
Android/iOS/Harmony | 回调 | Android 停止后进入 stopped,保留当前设备和媒体用于继续投屏;当前无会话时安全收口或返回控制失败。 |
getCastSessionState(options?) |
全平台 | CastSessionState |
降级端返回空会话状态。 |
getCastDiagnostics(options?) |
全平台 | CastDiagnostics |
不伪造 runtimeVerified。 |
exportCastSupportBundle(options?) |
全平台 | CastSupportBundle |
只导出运行态信息和建议动作。 |
inspectCastMediaSource(options) |
全平台 | CastMediaInspection |
不联网探测,只做静态风险判断。 |
onCastEvent(eventName, callback) |
全平台 | 持续监听 | eventName 为字符串,推荐传入 CastEventName 或 *。 |
offCastEvent(eventName, callback?) |
全平台 | 无 | callback 为空时移除该事件名下全部监听。 |
事件说明
事件回调签名为 (event: CastEvent) => void,eventName 为字符串。推荐传入 CastEventName 中的事件名,或传入 * 监听全部事件。
| 事件 | 说明 |
|---|---|
ready |
运行时初始化完成。 |
discoveryStart |
开始搜索设备。 |
discoveryStop |
停止搜索设备。 |
deviceFound |
发现单个设备。 |
deviceLost |
设备离线或被移除。 |
deviceListChange |
设备列表变化。 |
panelShow |
内置面板展示或业务入口触发。 |
panelHide |
内置面板关闭。 |
connectStart |
开始连接设备。 |
connected |
设备连接成功。 |
disconnected |
设备断开。 |
castStart |
开始投屏媒体。 |
stateChange |
会话状态变化。 |
progress |
播放进度变化。 |
volumeChange |
音量变化。 |
customAction |
内置面板选集、清晰度、主题、业务按钮等操作事件。 |
error |
投屏错误。 |
initCast(options)
说明 初始化投屏运行时,可选自动启动搜索。
参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | InitCastOptions | 是 | 初始化参数。 | 无 | debug / autoStartDiscovery / discoveryTimeoutMs / success / fail / complete |
| options.debug | boolean | 否 | 是否输出精简中文调试日志。 | false | true / false |
| options.autoStartDiscovery | boolean | 否 | 初始化后是否自动搜索设备。 | false | true / false |
| options.discoveryTimeoutMs | number | 否 | 搜索超时时间,单位毫秒。 | 8000 | 无 |
startDiscovery(options)
说明
开始搜索投屏设备。Android/iOS/Harmony 会搜索 DLNA DMR;模拟器、企业网络或组播受限时,可传 manualDeviceDescriptionUrl 指向已知 device.xml。iOS 的 AirPlay 仍通过系统路由入口选择,不做私有协议扫描。
参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | StartDiscoveryOptions | 是 | 搜索参数。 | 无 | timeoutMs / clearBeforeStart / manualDeviceDescriptionUrl / success / fail / complete |
| options.timeoutMs | number | 否 | 搜索超时时间,单位毫秒。 | 8000 | 无 |
| options.clearBeforeStart | boolean | 否 | 是否清空旧设备再搜索。 | true | true / false |
| options.manualDeviceDescriptionUrl | string | 否 | 手动指定 DLNA DMR 设备描述地址;例如模拟器访问电脑服务时可用 dmrDeviceUrl 或 10.0.2.2 场景。 |
无 | 无 |
showCastPanel(options)
说明
展示插件内置投屏面板。Android/iOS 是原生底部近全屏面板;Harmony 使用 ArkUI openBindSheet 底部近全屏面板承接搜索设备、选择设备、投屏当前媒体、状态卡、媒体进度、音量、3D 遥控控制台、选集、清晰度、暂停、恢复、停止、断开和状态查看;当窗口 UIContext 暂不可用时会降级到系统 ActionSheet,降级端建议用 useBuiltinUI:false 触发业务自定义入口。Android 点击“投屏”后先进入“投屏中...”加载态,成功后主按钮按播放状态显示“暂停/播放”;停止只停止远端播放,不断开设备,面板会切到“继续投屏”并可复用当前媒体继续投屏;进度条不会在未投屏或已停止时提前展示;Android 投屏成功后会按秒异步轮询 DLNA GetPositionInfo,只有电视端返回 positionSupported=true 时才推进面板进度;Android/iOS 在投屏成功且有时长后可拖拽进度条,松手后走真实 seekCast。
参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | CastPanelOptions | 否 | 面板配置。 | {} |
无 |
| options.useBuiltinUI | boolean | 否 | 是否使用插件内置 UI。 | true | true / false |
| options.theme | string | 否 | 内置面板主题。Harmony ArkUI 底部 Sheet 会按 dark / light 切换视觉,auto 首版按深色处理。 |
Android 默认 dark,iOS/Harmony 默认 auto |
dark / light / auto |
| options.title | string | 否 | 面板标题。 | 投屏到电视 | 无 |
| options.subtitle | string | 否 | 面板副标题。 | 请选择同一 Wi-Fi 下的设备 | 无 |
| options.media | CastMediaSource | 否 | 连接后控制台默认媒体,带 URL 时可直接投屏。 | 无 | 无 |
| options.mediaTitle | string | 否 | 控制台媒体标题。 | 当前媒体标题 | 无 |
| options.mediaSubtitle | string | 否 | 控制台媒体副标题。 | 无 | 无 |
| options.currentEpisodeIndex | number | 否 | 当前选集下标,从 0 开始。 | 0 | 无 |
| options.episodes | Array |
否 | 内置面板选集列表。 | [] |
无 |
| options.currentQuality | string | 否 | 当前清晰度 ID 或文案。 | 无 | 无 |
| options.qualities | Array |
否 | 内置面板清晰度列表。 | [] |
无 |
| options.currentTime | number | 否 | 业务传入的当前播放进度,单位秒;未传时使用插件会话进度。 | 当前会话进度 | 无 |
| options.duration | number | 否 | 业务传入的当前媒体总时长,单位秒;未传时使用插件会话时长。 | 当前会话时长 | 无 |
| options.showThemeToggle | boolean | 否 | 是否显示顶部单图标主题按钮。 | true | true / false |
| options.showEpisodeControls | boolean | 否 | 是否显示选集和上一集/下一集。 | true | true / false |
| options.showQualityControls | boolean | 否 | 是否显示清晰度切换。 | true | true / false |
| options.showRefresh | boolean | 否 | 是否显示扫描设备入口。 | true | true / false |
| options.showCustomAction | boolean | 否 | 是否显示业务自定义入口。 | false | true / false |
| options.customActionText | string | 否 | 业务入口文案。 | 使用业务自定义界面 | 无 |
选集或清晰度项带 url 时,点击对应按钮会派发 customAction,并尝试调用真实投屏流程;不带 url 时只派发业务事件,不会伪造投屏成功。业务可以把接口返回的播放历史通过 currentTime / duration 传给内置面板,作为投屏前展示和起播位置;真正进入投屏会话后,Android 面板优先使用电视端 GetPositionInfo 返回的真实播放进度,不再让业务起播点长时间冒充远端播放进度。
startCast(options)
说明
开始投屏远程媒体 URL。当前支持电视/盒子可访问的 http/https 视频和图片地址;图片建议显式传 mediaKind:'image'。
参数
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | StartCastOptions | 是 | 开始投屏参数。 | 无 | deviceId / media / autoConnect / success / fail / complete |
| options.deviceId | string | 否 | 目标设备 ID,未传时使用当前连接设备。 | 当前设备 | 无 |
| options.media | CastMediaSource | 是 | 媒体资源,支持远程视频或图片。 | 无 | 无 |
| options.autoConnect | boolean | 否 | 是否自动连接目标设备。 | true | true / false |
| options.media.url | string | 是 | 媒体 URL。 | 无 | http / https |
| options.media.title | string | 否 | 媒体标题。 | 无 | 无 |
| options.media.mediaKind | CastMediaKind | 否 | 媒体类型;传 image 时按图片投屏处理。 |
根据 MIME/扩展名推断 | video / image |
| options.media.mimeType | string | 否 | MIME 类型,例如 video/mp4、image/jpeg。 |
根据媒体类型兜底 | 无 |
| options.media.startPosition | number | 否 | 视频起播位置,单位秒;图片模式忽略。 | 0 | 无 |
seekCast(options)
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | SeekCastOptions | 是 | 跳转参数。 | 无 | position / success / fail / complete |
| options.position | number | 是 | 目标位置,单位秒。 | 无 | 大于等于 0 |
setCastVolume(options)
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | SetCastVolumeOptions | 是 | 音量参数。 | 无 | volume / success / fail / complete |
| options.volume | number | 是 | 音量,范围 0-1。 | 无 | 0-1 |
getCastDiagnostics(options?)
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | GetCastDiagnosticsOptions | 否 | 诊断参数。 | { includeDevices:false } |
无 |
| options.includeDevices | boolean | 否 | 是否带上设备列表。 | false | true / false |
Harmony SSDP 诊断字段
| 字段 | 类型 | 说明 |
|---|---|---|
| ssdpResponseCount | number | 最近一次 SSDP 搜索收到的 UDP 响应数量;其它平台可不返回。 |
| ssdpLocationCount | number | 最近一次 SSDP 搜索成功解析出 LOCATION 的响应数量;其它平台可不返回。 |
| ssdpDecodeErrorCount | number | 最近一次 SSDP 响应解码失败数量;其它平台可不返回。 |
| lastSsdpMessagePreview | string | 最近一次 SSDP 响应预览,用于区分未收到响应、解码失败或缺少 LOCATION;其它平台可不返回。 |
exportCastSupportBundle(options?)
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | ExportCastSupportBundleOptions | 否 | 售后诊断包参数。 | { includeDevices:true, includeRecentEvents:true, maxEvents:20 } |
无 |
| options.includeDevices | boolean | 否 | 是否包含设备列表。 | true | true / false |
| options.includeRecentEvents | boolean | 否 | 是否包含最近事件。 | true | true / false |
| options.maxEvents | number | 否 | 最近事件最大数量。 | 20 | 1-80 |
inspectCastMediaSource(options)
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| options | InspectCastMediaSourceOptions | 是 | 媒体源预检参数。 | 无 | media / success / fail / complete |
| options.media | CastMediaSource | 是 | 待检查媒体源。 | 无 | 无 |
返回值说明
CastCapabilities
| 字段 | 类型 | 说明 |
|---|---|---|
| supported | boolean | 当前平台是否支持真实投屏。 |
| platform | string | 平台名称。 |
| adapter | string | 适配器,例如 dlna / airplay / fallback。 |
| discovery | boolean | 是否支持设备搜索。 |
| builtinPanel | boolean | 是否支持内置面板。 |
| mediaCast | boolean | 是否支持媒体 URL 投屏。 |
| systemRoute | boolean | 是否接入系统路由。 |
| pause | boolean | 是否支持暂停。 |
| resume | boolean | 是否支持恢复。 |
| seek | boolean | 是否支持进度跳转。 |
| volume | boolean | 是否支持音量控制。 |
| requiresCustomBase | boolean | 是否建议自定义基座。 |
| reason | string | 不支持原因。 |
CastSessionState
| 字段 | 类型 | 说明 |
|---|---|---|
| initialized | boolean | 是否已初始化。 |
| discovering | boolean | 是否正在搜索设备。 |
| state | CastConnectionState | 当前连接/播放状态;Android stopped 表示远端播放已停止但当前设备和媒体仍可用于继续投屏。 |
| currentDevice | CastDevice | null | 当前设备。 |
| currentMedia | CastMediaSource | null | 当前媒体。 |
| devices | Array |
设备列表。 |
| currentTime | number | 当前播放进度,单位秒。 |
| duration | number | 媒体总时长,单位秒。 |
| volume | number | 音量,范围 0-1。 |
| lastError | CastFail | null | 最近一次错误。 |
会话进度快照来源:Android、iOS DLNA 和 Harmony 优先通过 GetPositionInfo 获取 RelTime / TrackDuration;Android 内置面板投屏成功后会异步轮询该快照,暂停、停止和断开时停止轮询;iOS AirPlay 路径通过 AVPlayer.currentTime 与媒体时长同步。
CastMediaInspection
| 字段 | 类型 | 说明 |
|---|---|---|
| castable | boolean | 是否适合进入首版投屏流程。 |
| httpUrl | boolean | 是否为 http/https。 |
| localFile | boolean | 是否疑似本地文件。 |
| drmSuspected | boolean | 是否疑似 DRM 或加密流。 |
| authSuspected | boolean | 是否疑似私有鉴权。 |
| likelyVideo | boolean | 是否疑似视频媒体。 |
| likelyImage | boolean | 是否疑似图片媒体。 |
| mediaKind | CastMediaKind | 'unknown' | 预检推断出的媒体类型。 |
| riskFlags | Array |
风险标记,例如 https-dlna-risk。 |
| suggestions | Array |
中文建议。 |
| message | string | 中文摘要。 |
错误码
| 错误码 | 含义 | 说明 |
|---|---|---|
| 9030001 | unsupported | 当前平台不支持真实投屏或未打入自定义基座。 |
| 9030002 | invalid params | 参数不合法,例如媒体 URL 为空。 |
| 9030003 | context unavailable | 运行时上下文不可用。 |
| 9030004 | discovery failed | 搜索投屏设备失败。 |
| 9030005 | device not found | 未找到可用设备。 |
| 9030006 | connect failed | 连接设备失败。 |
| 9030007 | media unsupported | 媒体地址不可投屏。 |
| 9030008 | cast failed | 投屏播放失败。 |
| 9030009 | control failed | 投屏控制命令失败。 |
| 9030010 | panel failed | 投屏内置界面展示失败。 |
权限说明
Android 需要以下权限,插件已在 AndroidManifest.xml 声明:
| 权限 | 说明 |
|---|---|
android.permission.INTERNET |
访问 DLNA 设备描述、SOAP 控制地址和媒体 URL。 |
android.permission.ACCESS_NETWORK_STATE |
判断网络状态。 |
android.permission.ACCESS_WIFI_STATE |
获取 Wi-Fi 状态。 |
android.permission.CHANGE_WIFI_MULTICAST_STATE |
使用 Wi-Fi multicast lock,提升 SSDP 搜索稳定性。 |
iOS 使用 DLNA/UPnP 局域网发现与 SOAP 控制,同时保留 AirPlay 系统路由和 AVPlayer 外部播放能力;不做私有 AirPlay 扫描。1.0.16 面向已获 Apple Multicast Networking 授权的 iOS 构建,默认保留 NSLocalNetworkUsageDescription、ATS 本地网络例外,并在 UTS.entitlements 内置 com.apple.developer.networking.multicast,点击搜索会进入真实 SSDP 组播发现。业务必须确认 App ID 已启用 Multicast Networking、provisioning profile 已重新生成且云打包选择的是该新描述文件;未获批客户请继续使用 manualDeviceDescriptionUrl 指向已知 device.xml 验证 DLNA 解析与 SOAP 控制链路,或使用不声明 multicast 的保护构建。
Harmony 使用 DLNA/UPnP 局域网发现与 SOAP 控制,需要在 utssdk/app-harmony/module.json5 声明 ohos.permission.INTERNET,用于访问 DLNA device.xml、SSDP/UDP 搜索和 SOAP 控制地址。
原生配置文件
| 平台 | 文件 | 说明 |
|---|---|---|
| Android | utssdk/app-android/AndroidManifest.xml |
声明网络、Wi-Fi 和组播权限,并绑定 android:networkSecurityConfig。 |
| Android | utssdk/app-android/res/xml/lizhao_cast_screen_network_security_config.xml |
允许局域网 DLNA/UPnP 明文 HTTP,包含 cleartextTrafficPermitted="true"。 |
| Android | utssdk/app-android/assets / libs / res |
资源占位目录,便于后续扩展。 |
| iOS | utssdk/app-ios/Info.plist |
包含 NSAllowsLocalNetworking 与 App Transport Security 本地网络例外,不默认启用 NSAllowsArbitraryLoads。 |
| iOS | utssdk/app-ios/UTS.entitlements |
1.0.16 已内置 com.apple.developer.networking.multicast,用于已获 Apple Multicast Networking 授权的 iOS SSDP/UPnP 组播发现;未获批描述文件会在云打包阶段失败。 |
| iOS | utssdk/app-ios/PrivacyInfo.xcprivacy |
隐私清单。 |
| iOS | utssdk/app-ios/Frameworks / Libs / Resources |
资源与原生依赖占位目录。 |
| Harmony | utssdk/app-harmony/module.json5 |
声明 ohos.permission.INTERNET,用于 DLNA/UPnP 设备描述、SSDP 和 SOAP 控制。 |
Android 9/API 28+ 默认限制明文 HTTP,而许多 DLNA DMR 设备描述和控制地址仍是局域网 HTTP,所以插件配置了 lizhao_cast_screen_network_security_config。这只用于 DLNA/UPnP 局域网能力,不建议业务把所有公网请求都放开为 cleartext。
iOS 的 App Transport Security 针对 DLNA/UPnP 本地网络与 AirPlay 接入做边界说明,包含 NSAllowsLocalNetworking,不建议在业务中无差别放开 NSAllowsArbitraryLoads。若 iOS 自动搜索只能看到 AirPlay 系统路由,请先确认当前基座运行诊断版本是否为 1.0.16,并确认实际安装包的 entitlements 包含 com.apple.developer.networking.multicast。如果仍在日志中看到 ios-multicast-entitlement-required,通常说明设备上运行的仍是旧保护构建或未重新安装最新 iOS 自定义基座;1.0.16 默认会进入自动 SSDP 搜索。
iOS 自动搜索与 Multicast 权限申请
同一 Wi-Fi 只是 DLNA/UPnP 设备可达的网络前提;iOS 真机自动搜索还依赖 SSDP 组播,目标地址通常是 239.255.255.250:1900。Apple 将本地网络 multicast/broadcast 归入受控能力,业务 App 必须获批 com.apple.developer.networking.multicast 后才能使用 1.0.16 的自动 SSDP 搜索;未获批时不要使用内置该 entitlement 的构建,否则云打包会因描述文件能力不匹配而失败。
客户要开启 iOS 自动 SSDP 搜索时,需要按下面顺序处理:
- 使用 Apple Developer 的 Account Holder 或 Admin 账号登录。
- 打开 Apple 官方申请页:Multicast Networking Entitlement Request。
- 选择或填写业务 App 的 Bundle ID,例如自定义基座实际使用的
com.xxx.xxx。 - 在用途说明中写清楚:App 提供 DLNA/UPnP 媒体投屏,需要在用户本地 Wi-Fi 内通过 SSDP UDP multicast
239.255.255.250:1900发现电视、盒子或 Macast 等 DMR 接收端;部分 DLNA 设备不提供 Bonjour 服务,因此 Bonjour 不能完全替代 SSDP;插件仅用于本地网络设备发现,不采集个人信息。 - Apple 审批通过后,到 Apple Developer 后台的
Certificates, Identifiers & Profiles,在对应 App ID 上启用 Multicast Networking managed capability。 - 重新生成并下载包含该能力的 provisioning profile。
- 确认
utssdk/app-ios/UTS.entitlements已包含:
<key>com.apple.developer.networking.multicast</key>
<true/>
- 使用新的 provisioning profile 重新打 iOS 自定义基座,然后再测试“搜索设备”自动发现;诊断日志中的
version应显示1.0.16。
未获批前,客户仍可使用示例页“手动设备地址”输入框或 API 的 manualDeviceDescriptionUrl,直接填写电视、盒子或 Macast 的 device.xml/description.xml 地址验证 DLNA 解析、连接、投屏、暂停、恢复、音量、进度和停止链路。这条链路不等于自动发现成功,但能证明同一 Wi-Fi 下 HTTP 访问与 SOAP 控制是否可用。
相关 Apple 文档:
- Multicast Networking Entitlement Request
- Multicast Networking entitlement
- Provisioning with managed capabilities
自定义基座说明
App Android / App iOS / App Harmony 使用真实原生投屏能力时必须重新制作自定义基座。未打自定义基座时的表现通常是:
| 表现 | 原因 | 处理方式 |
|---|---|---|
supported:false |
当前端为降级实现或原生插件未进入基座。 | 重新制作并安装包含 lizhao-cast-screen 的自定义基座。 |
uts插件[lizhao-cast-screen]编译失败 |
基座未包含当前 UTS 插件或旧 runtime 未刷新。 | 重新打包基座并确认手机端外部 UTS runtime 已清理。 |
parameter options 或 options 为空 |
Android 旧代理或旧 dex 仍在运行。 | 重新安装最新基座,必要时清理手机端外部 UTS runtime,并确认 base.apk 中包含 UTSSDKModulesLizhaoCastScreenInitCastOptionsJSONObject、CastScreenNative。 |
AUTO_DMR_INIT_THROW |
自动演示入口初始化失败,通常与基座或运行时不一致有关。 | 先确认已运行最新自定义基座,再检查日志中的错误码。 |
Provisioning profile doesn't include the Multicast Networking capability |
1.0.16 的 iOS UTS.entitlements 已声明 com.apple.developer.networking.multicast,但 App ID 或描述文件未获 Apple 授权。 |
使用已开通 Multicast Networking 后重新生成的 provisioning profile 打包;未获批前用 manualDeviceDescriptionUrl 验证 device.xml,或使用不声明 multicast 的保护构建。 |
iOS 点击搜索返回 9030004,details 包含 ios-multicast-entitlement-required |
当前运行的仍是 1.0.13 或更早保护构建,或旧自定义基座没有刷新到 1.0.16。 |
重新安装用 1.0.16 和新 provisioning profile 打出的 iOS 自定义基座;打开诊断确认 version:"1.0.16" 后再测自动搜索。 |
如果 Android 系统通知栏的“屏幕投射”可以看到设备,但插件搜索不到设备,要先区分协议:系统入口通常是 Miracast 或系统投屏路由,插件首版搜索的是 DLNA DMR 媒体投屏设备。请确认电视/盒子开启了 DLNA 或媒体投屏接收能力。
Harmony 真实投屏同样要求电视/盒子支持 DLNA DMR,并与手机处于同一 Wi-Fi。若真机环境阻断 SSDP 组播,优先使用 manualDeviceDescriptionUrl 指向电视/盒子的 device.xml 验证 HTTP 拉取、设备解析和 SOAP 控制链路;Harmony 首版不提供屏幕镜像、Miracast 或系统投射能力。
如果投屏时出现 UPnP 716 Resource not found,说明电视端无法访问传入媒体地址。常见处理方式:
- 使用电视可直接访问的普通
httpMP4 做验证。 - 避免登录态、Cookie、Authorization、临时签名过短或 DRM 资源。
- 对 HTTPS 地址留意
https-dlna-risk,部分老电视不支持 HTTPS 媒体播放。 - 手机能播放不代表电视能访问,电视端必须能直接请求该 URL。
- Windows 上同时出现
Macast(yunxi)和yunxi时,Macast(yunxi)是 Macast 接收器,yunxi通常是 Windows 自带 Digital Media Renderer;后者对远程 HTTP/HTTPS URL 支持更严格,仍可能返回 716,测试 Macast 请优先选择Macast(yunxi)。 - iOS
1.0.16在 Windows Digital Media Renderer 返回 716 时会自动尝试备用 DIDL 元数据;如果备用后仍返回 716,继续按接收端无法访问或不支持该媒体 URL 处理。
iOS 路由事件说明
iOS 的 DLNA 设备发现和连接会返回真实 dlna 设备;AirPlay 仍使用系统路由,不做私有 AirPlay 反射,也不会在初始化且未选择路由时伪造一次断开事件。只有 DLNA 搜索/连接/控制、系统路由变化、外部播放状态变化或用户操作导致状态变化时,才会通过 deviceFound / deviceListChange / stateChange / connected / disconnected / error 等事件回传。
Harmony 搜索与控制说明
Harmony 的真实设备发现会返回 dlna 设备,控制链路使用 AVTransport / RenderingControl SOAP。SSDP 搜索受路由器、同网段隔离和系统网络策略影响较大;真机首测建议先传入 manualDeviceDescriptionUrl 验证 device.xml 与 SOAP,再验证同 Wi-Fi 自动搜索。showCastPanel 在 Harmony 会优先弹出 Android 风格 ArkUI 底部 Sheet 内置面板,业务仍可用 useBuiltinUI:false 自行展示设备列表和控制台;如果当前窗口 UIContext 获取失败,插件会降级到系统 ActionSheet 继续承接搜索和播控。
Harmony SSDP 响应由 @ohos.net.socket 返回 ArrayBuffer,插件会使用 @ohos.util.TextDecoder 解码后解析 LOCATION。如果同 Wi-Fi 下自动搜索仍为空,可先点“诊断快照”查看 ssdpResponseCount / ssdpLocationCount / ssdpDecodeErrorCount / lastSsdpMessagePreview:ssdpResponseCount=0 通常表示设备或路由未把 SSDP 响应回传到 Harmony 端;ssdpResponseCount>0 但 ssdpLocationCount=0 表示收到响应但没有解析到 LOCATION,建议把日志提供给开发侧继续适配。
uni-app 调用示例
<script>
import * as CastScreen from '@/uni_modules/lizhao-cast-screen'
export default {
data() {
return {
devices: []
}
},
onLoad() {
CastScreen.initCast({ debug: true })
CastScreen.onCastEvent('*', this.handleCastEvent)
},
onUnload() {
CastScreen.offCastEvent('*', this.handleCastEvent)
},
methods: {
handleCastEvent(event) {
console.log('投屏事件', event)
},
openPanel() {
CastScreen.showCastPanel({ theme: 'auto' })
},
startSearch() {
CastScreen.startDiscovery({
timeoutMs: 8000,
success: () => {
this.devices = CastScreen.getDiscoveredDevices()
}
})
}
}
}
</script>
uni-app x 调用示例
import * as CastScreen from '@/uni_modules/lizhao-cast-screen'
CastScreen.initCast({
debug: true,
success: () => {
console.log('投屏运行时已初始化')
}
})
const caps = CastScreen.getCastCapabilities(null)
if (caps.supported) {
CastScreen.showCastPanel({
theme: 'dark',
title: '投屏到电视',
subtitle: '请选择同一 Wi-Fi 下的设备'
})
}
注意事项
- 首版定位为“远程媒体 URL 投屏”,不是屏幕镜像、录屏推流或 DRM 破解插件;本地文件、DRM、需登录鉴权的私有视频需要先转换为电视可访问的远程媒体 URL。
- Android 搜索不到设备时,先确认电视支持 DLNA DMR,而不只是支持 Miracast。
- iOS DLNA 投屏要求手机与电视/盒子在同一局域网,AirPlay 路径必须通过系统路由选择,不绕过系统能力。
- Harmony DLNA 投屏要求手机与电视/盒子在同一局域网;若 SSDP 受限,优先使用
manualDeviceDescriptionUrl做真机链路验证。 - Web/H5 与小程序端允许展示业务自定义入口,但不得伪造设备发现、连接或投屏成功。
- 媒体投屏失败时,先用
inspectCastMediaSource检查 URL,再用exportCastSupportBundle导出诊断信息给售后或开发排查。
作者系列UTS插件
以下为已在 DCloud 插件市场上架的作者系列 UTS 插件,可按业务场景组合使用。未列出的插件表示当前未确认公开市场页,后续上架后再补充。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-nfc-pro |
NFC 标签读写、NDEF、IsoDep 与诊断 | 查看插件 |
lizhao-float-window |
悬浮窗、画中画、权限与诊断 | 查看插件 |
lizhao-device-id |
设备标识、隐私策略与诊断 | 查看插件 |
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列、倍速与事件 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-share-plus |
系统分享、远程文件下载后分享 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移、备份与诊断 | 查看插件 |
lizhao-icon-pro |
SVG 图标组件、多主题与缓存 | 查看插件 |
lizhao-cast-screen |
DLNA 投屏、AirPlay 路由入口 | 查看插件 |
lizhao-call-kit |
电话、短信、通讯录原生能力 | 查看插件 |
lizhao-app-keepalive |
应用保活、唤醒、自愈与报告 | 查看插件 |
lizhao-doc-corrector |
文档扫描、矫正、增强与识别 | 查看插件 |
lizhao-emu-detect |
模拟器环境检测、风险评分与证据 | 查看插件 |

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