更新记录

1.0.0(2026-03-23) 下载此版本

mech1-vpn-detector

mech1-vpn-detector 是一个用于 uni-app x 项目的 UTS API 插件,用来检测当前设备网络是否处于 VPN 环境。

插件信息卡片

项目 内容
插件名称 mech1-vpn-detector
当前版本 1.0.0
最近更新时间 2026-03-23
插件定位 uni-app x App 侧 VPN 网络环境检测插件
插件类型 UTS API 插件
核心能力 同步检测 VPN、支持 Android/iOS、支持项目级二次封装
适用场景 启动提示、回前台复检、设置页手动检测、网络异常排障引导
真实检测平台 Android、iOS
可编译调用平台 Android、iOS、Web、未单独实现平台兜底
当前 HBuilderX 要求 建议使用 3.1.0+ 以支持 uni_modules;当前项目验证环境为 5.04.2026031906-alpha

核心能力速览

  • 提供同步 API isVpnEnabled(): boolean
  • Android 基于 ConnectivityManager / NetworkCapabilities.TRANSPORT_VPN 判断
  • iOS 基于 CFNetworkCopySystemProxySettings() 做启发式判断
  • Web 与未实现平台可编译、可调用,但默认返回 false
  • 易于接入启动检测、前后台切回检测、设置页测试入口等业务场景

安装与接入

这一节按更接近插件市场发布页的方式整理,方便开发者快速完成导入、调用和验证。

1. 安装方式

你可以用以下任一方式接入:

方式 A:直接使用当前项目中的现成插件目录

本项目已经包含插件目录:

uni_modules/mech1-vpn-detector

如果你是在本项目内开发,通常不需要额外安装。

方式 B:复制到其他 uni-app x 项目

将以下目录整体复制到目标项目:

uni_modules/mech1-vpn-detector

复制后建议重新打开 HBuilderX 或重新编译一次工程,让 uni_modules 索引刷新。

2. 导入方式

.uvue.uts 中按插件根目录导入,不要直接导入平台实现文件:

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

推荐做法:

  • 从插件根目录导入
  • 通过业务层工具函数二次封装后再在页面使用

不推荐做法:

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts'

3. 最小 HBuilderX 要求

参考 uni_modules 规范与 DCloud 插件市场常见要求,建议如下:

  • uni_modules 机制建议使用 HBuilderX 3.1.0+
  • 本插件用于 uni-app x,建议使用较新的 uni-app x / HBuilderX 版本
  • 当前项目实际验证环境:HBuilderX 5.04.2026031906-alpha

如果你在较旧版本 HBuilderX 中遇到以下问题:

  • uni_modules 无法识别
  • UTS 插件类型提示异常
  • 平台入口文件没有正确索引

优先建议升级 HBuilderX 后再验证。

4. 推荐验证步骤

为了更接近真实发布页里的“快速验证”,建议开发者按下面顺序完成验证。

4.1 基础调用验证

在任意页面或工具文件中加入:

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

const vpnEnabled = isVpnEnabled()
console.log('vpnEnabled =', vpnEnabled)

验证目标:

  • 工程能正常编译
  • 调用无报错
  • 能获得布尔值结果

4.2 Android 真机验证

建议步骤:

  1. 关闭 VPN,进入页面调用一次,确认返回 false
  2. 打开系统 VPN 或 VPN App,等待连接完成
  3. 再次调用 isVpnEnabled(),确认返回 true
  4. 如项目已接入设置页检测按钮,可直接点“立即检测当前 VPN 状态”验证

4.3 iOS 真机验证

建议步骤:

  1. 关闭 VPN,调用一次,确认返回 false
  2. 打开 VPN 后重新进入页面、切回前台,或手动点检测按钮
  3. 观察是否命中启发式检测结果

注意:

  • iOS 可能因不同 VPN 产品实现差异而出现漏报或误报
  • 建议用多种 VPN 连接模式交叉验证

4.4 Web 验证

Web 端验证重点不是“能否检测出 VPN”,而是:

  • 工程是否能正常编译
  • 调用是否安全
  • 返回值是否稳定为 false

4.5 项目级完整接入验证

如果你采用本项目完整接入方案,建议额外验证:

  1. 启动时是否按预期弹出提示
  2. 点击“本次启动不再提示”后,本轮启动是否静默
  3. 设置页总开关关闭后,是否不再弹窗
  4. 切到后台再回前台后,是否会根据当前 VPN 状态重新检测
  5. 设置页“立即检测当前 VPN 状态”是否能即时反馈结果

本插件当前已在本项目中完成以下接入能力:

  • App 启动时检测 VPN 环境
  • App 从后台切回前台时二次检测 VPN 环境
  • 配合浮窗组件提示用户当前网络可能影响服务连接
  • 支持“本次启动不再提示”
  • 支持设置页总开关
  • 支持设置页手动测试当前 VPN 状态

如果你是第一次接触本插件,建议按下面顺序阅读:

  1. 先看“插件能力概览”
  2. 再看“快速开始”
  3. 再看“完整接入方案”
  4. 最后看“文件结构与每个文件的作用”

1. 插件能力概览

1.1 对外 API

本插件当前只对外暴露 1 个同步方法:

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

const vpnEnabled = isVpnEnabled()

返回值:

  • true:当前检测到设备处于 VPN 环境
  • false:当前未检测到 VPN 环境,或当前平台不支持检测

1.2 平台行为

平台 实现方式 返回结果说明
Android 通过 ConnectivityManager + NetworkCapabilities.TRANSPORT_VPN 判断当前活动网络 准确度较高,适合业务提示与运行时检测
iOS 通过 CFNetworkCopySystemProxySettings() 读取系统网络作用域接口名,并匹配 utuntaptunpppipsec 等前缀 启发式判断,适合风险提示,不建议当作强安全校验
Web 直接返回 false Web 不提供原生 VPN 状态判断能力
其他未单独实现平台 通过根入口兜底返回 false 避免跨端编译报错

1.3 平台兼容性

参考 DCloud 插件市场常见展示方式,这里补充一份更直观的平台兼容性说明,便于开发者像查看 hans-blur-viewlime-transition 一样快速判断可用范围。

1.3.1 插件本体兼容性

平台 是否支持 说明
Android 原生检测,基于当前活动网络能力判断
iOS 启发式检测,基于系统网络作用域接口名判断
鸿蒙 - 当前未实现专用平台入口,默认走兜底返回 false
Web Chrome 可编译可调用,但检测结果固定为 false
Web Safari 可编译可调用,但检测结果固定为 false
微信小程序 可编译可调用,但当前无专用实现,默认返回 false
其他未单独实现平台 utssdk/index.uts 兜底,统一返回 false

1.3.2 项目内完整接入链路兼容性

能力 Android iOS 鸿蒙 Web
isVpnEnabled() 插件调用 -
返回真实 VPN 检测结果 - -
启动时自动检测 - -
前后台切回二次检测 - -
毛玻璃风险浮窗 取决于项目 UI 方案 √(模拟毛玻璃)
设置页总开关 取决于项目接入
设置页手动检测按钮 取决于项目接入 √(结果固定未检测到)

1.3.3 与常见插件市场展示风格的对应关系

  • 类似 hans-blur-view:会强调“平台兼容性 + 运行效果差异 + 标准基座/自定义基座限制”
  • 类似 lime-transition:会强调“哪些平台可编译、哪些平台可运行、哪些平台行为一致或退化”
  • 对于 mech1-vpn-detector,最重要的不是“能不能编译”,而是“返回值是否真实有效”
  • 因此阅读兼容性时,要区分“支持编译调用”和“支持真实检测”这两个层次

1.4 适用场景

  • 在 App 启动后提醒用户当前网络可能影响访问
  • 在 WebView / 内嵌网页 / 接口访问异常时,给出“请关闭 VPN 后重试”的引导
  • 在设置页中提供网络环境自检能力
  • 在前后台切换时做轻量级网络状态复查

2. 快速开始

2.1 目录位置

插件位于:

uni_modules/mech1-vpn-detector

根据 uni-app x UTS 插件规范,插件的核心目录是 utssdk。官方文档中明确说明:

  • interface.uts 用于“声明插件对外暴露的 API,必需”
  • 分平台目录如 app-android/index.utsapp-ios/index.utsweb/index.uts 用于各平台具体实现
  • 当根目录和平台目录同时存在时,优先使用平台目录实现

2.2 最简单调用方式

在任意 .uvue / .uts 文件中直接引入:

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

const vpnEnabled = isVpnEnabled()
if (vpnEnabled) {
    uni.showToast({
        title: '当前处于 VPN 网络环境',
        icon: 'none'
    })
}

2.3 推荐调用时机

建议在以下节点调用:

  • App 首次进入主页面后
  • 用户从后台切回前台时
  • 打开依赖网络的关键页面前
  • 设置页手动检测按钮点击时

不建议高频轮询调用。

3. 完整接入方案

本项目已经做了一套完整接入,你可以直接复用。

3.1 项目内现有接入链路

A. 插件底层检测

文件:uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts

  • Android 直接读取当前活动网络能力
  • 如果活动网络包含 TRANSPORT_VPN,返回 true

文件:uni_modules/mech1-vpn-detector/utssdk/app-ios/index.uts

  • iOS 调用 Swift 混编类 Mech1VpnDetectorNative
  • Swift 侧使用 CFNetwork 公开 API 进行启发式判断

B. 项目级状态管理

文件:utils/vpn-notice.uts

这个文件不是插件本体,但它是项目接入插件时最关键的一层封装,负责:

  • 统一读取插件检测结果
  • 管理“是否开启 VPN 提示”的持久化配置
  • 管理“本次启动不再提示”的会话级状态
  • 管理 App 前后台切换时触发的检测事件

C. UI 提示浮窗

文件:components/common/VpnNoticePopup.uvue

负责显示:

  • 渐变毛玻璃提示卡片
  • 5 秒自动关闭倒计时
  • 手动关闭按钮
  • “本次启动不再提示”按钮

D. 页面联动入口

文件:pages/tabs/layout.uvue

负责:

  • 页面首次进入时准备 VPN 检测结果
  • 避开隐私说明、更新提示、公告提示等遮罩冲突
  • 在合适时机显示 VPN 浮窗
  • App 回到前台时执行二次检测

E. App 前后台事件转发

文件:App.uvue

负责:

  • onShow 中发出 VPN_NOTICE_APP_FOREGROUND_EVENT
  • 通知布局页进行“回前台后的二次检测”

F. 设置页控制入口

文件:pages/tabs/more/settings/settings.uvue

负责:

  • 控制总开关“VPN 环境提示”
  • 显示“本次启动状态”
  • 提供“恢复本次启动提醒”按钮
  • 提供“立即检测当前 VPN 状态”测试入口

4. 插件 API 文档

4.1 isVpnEnabled(): boolean

定义文件:uni_modules/mech1-vpn-detector/utssdk/interface.uts

源码如下:

export type IsVpnEnabled = () => boolean

实现导出名称:

export const isVpnEnabled: IsVpnEnabled = function (): boolean {
    ...
}

参数

无。

返回值

  • true:检测到 VPN
  • false:未检测到 VPN,或当前平台不支持

特点

  • 同步调用
  • 零配置
  • 适合页面逻辑中直接判断
  • 适合再次封装到项目级工具中统一管理

5. 各平台实现说明

5.1 Android 实现说明

文件:uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts

当前实现逻辑:

  1. 通过 UTSAndroid.getAppContext() 获取应用上下文
  2. 通过 Context.CONNECTIVITY_SERVICE 获取 ConnectivityManager
  3. 读取当前 activeNetwork
  4. 通过 getNetworkCapabilities(activeNetwork) 获取网络能力
  5. 调用 hasTransport(NetworkCapabilities.TRANSPORT_VPN) 判断是否为 VPN 网络

核心代码示例:

const activeNetwork = connectivityManager.getActiveNetwork()
if (activeNetwork == null) {
    return false
}

const capabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
if (capabilities == null) {
    return false
}

return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) == true

为什么 Android 端没有用 Kotlin 混编?

因为这部分系统 API 逻辑足够简单,直接纯 UTS 即可完成,维护成本更低,编译链更简单。

5.2 iOS 实现说明

文件:

  • uni_modules/mech1-vpn-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-ios/Mech1VpnDetectorNative.swift

iOS 没有像 Android 一样通用、稳定、面向普通应用的公开 API 来直接返回“当前是否启用 VPN”。

因此当前实现采用启发式方案:

  1. 通过 CFNetworkCopySystemProxySettings() 获取系统网络代理配置
  2. 读取 kCFNetworkProxiesScoped 对应的网络接口集合
  3. 检查接口名是否存在典型 VPN 虚拟网卡前缀,如:
    • utun
    • tap
    • tun
    • ppp
    • ipsec

核心 Swift 逻辑示例:

guard let scoped = proxySettings[kCFNetworkProxiesScoped as String] as? NSDictionary else {
    return false
}

let keys = scoped.allKeys.compactMap { $0 as? String }
for key in keys {
    let lowercasedKey = key.lowercased()
    for prefix in vpnInterfacePrefixes {
        if lowercasedKey.hasPrefix(prefix) {
            return true
        }
    }
}

iOS 方案局限性

这很重要,开发者必须明确:

  • 这是启发式判断,不是绝对准确的系统级事实判断
  • 适合做 UI 提示、风险提醒、排障辅助
  • 不适合做强风控、强安全校验、强业务阻断
  • 某些 VPN 可能漏报
  • 某些特殊网络环境可能误报

5.3 Web 与其他平台实现说明

文件:

  • uni_modules/mech1-vpn-detector/utssdk/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/web/index.uts

这两个文件统一返回 false,用于:

  • 保证 Web 编译通过
  • 保证其他未实现平台不会报错
  • 明确插件当前主要服务于 App 端

6. 文件结构与每个文件的作用

插件目录结构如下:

uni_modules/
└─ mech1-vpn-detector/
   ├─ package.json
   ├─ readme.md
   └─ utssdk/
      ├─ interface.uts
      ├─ index.uts
      ├─ web/
      │  └─ index.uts
      ├─ app-android/
      │  └─ index.uts
      └─ app-ios/
         ├─ index.uts
         └─ Mech1VpnDetectorNative.swift

下面是每个文件的职责说明。

6.1 package.json

路径:uni_modules/mech1-vpn-detector/package.json

作用:

  • 声明插件 ID、名称、版本、描述
  • 让 uni_modules 正确识别该插件
  • 作为插件发布与依赖识别的基础元数据文件

6.2 readme.md

路径:uni_modules/mech1-vpn-detector/readme.md

作用:

  • 说明插件怎么用
  • 解释每个平台的实现差异
  • 帮助项目开发者快速接入或二次维护

6.3 utssdk/interface.uts

路径:uni_modules/mech1-vpn-detector/utssdk/interface.uts

作用:

  • 定义插件对外暴露的类型签名
  • 让 HBuilderX 为调用方提供类型提示
  • 作为“声明层”,与各平台 index.uts 对应

6.4 utssdk/index.uts

路径:uni_modules/mech1-vpn-detector/utssdk/index.uts

作用:

  • 作为非 App / 未单独实现平台的兜底入口
  • 默认返回 false
  • 避免平台缺失实现时报错

6.5 utssdk/web/index.uts

路径:uni_modules/mech1-vpn-detector/utssdk/web/index.uts

作用:

  • 明确 Web 平台行为
  • 统一返回 false
  • 让 Web 端编译表现更明确、更易理解

6.6 utssdk/app-android/index.uts

路径:uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts

作用:

  • Android 平台的核心检测实现
  • 直接操作 Android 系统网络能力 API
  • 不依赖 Kotlin 混编

6.7 utssdk/app-ios/index.uts

路径:uni_modules/mech1-vpn-detector/utssdk/app-ios/index.uts

作用:

  • iOS 平台的 UTS 入口
  • 负责桥接到 Swift 混编类

6.8 utssdk/app-ios/Mech1VpnDetectorNative.swift

路径:uni_modules/mech1-vpn-detector/utssdk/app-ios/Mech1VpnDetectorNative.swift

作用:

  • iOS 平台原生混编实现
  • 使用 FoundationCFNetwork 进行启发式检测
  • 暴露 Mech1VpnDetectorNative.isVpnEnabled() 给 UTS 调用

7. 在项目中单独使用插件

如果你不需要本项目现有的浮窗、设置页、会话状态管理,只想单独使用插件做一次检测,可以这样写。

7.1 在页面中直接调用

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

export default {
    onShow() {
        const vpnEnabled = isVpnEnabled()
        if (vpnEnabled) {
            uni.showToast({
                title: '检测到 VPN 网络环境',
                icon: 'none'
            })
        }
    }
}

7.2 在工具函数中封装

import { isVpnEnabled } from '@/uni_modules/mech1-vpn-detector'

export function checkVpnAndNotify(): boolean {
    const enabled = isVpnEnabled() == true
    if (enabled) {
        uni.showToast({
            title: '当前网络处于 VPN 环境',
            icon: 'none'
        })
    }
    return enabled
}

8. 本项目完整使用教程

如果你想按本项目现有方式完整接入,请按下面步骤理解。

第一步:保留插件本体

确保以下文件存在:

  • uni_modules/mech1-vpn-detector/package.json
  • uni_modules/mech1-vpn-detector/utssdk/interface.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-ios/Mech1VpnDetectorNative.swift

第二步:增加项目级状态封装

项目使用的是 utils/vpn-notice.uts 这一层封装,而不是在页面里到处直接调用插件。

这样做的好处:

  • 页面层更干净
  • 提示开关可统一管理
  • 会话免打扰可统一管理
  • 回前台二次检测逻辑只写一次

第三步:增加提示浮窗 UI

components/common/VpnNoticePopup.uvue 中维护统一样式与交互。

这样做的好处:

  • UI 统一
  • 可以单独演进视觉效果
  • 页面里只处理显示时机,不关心具体样式细节

第四步:在主布局页做显示调度

本项目在 pages/tabs/layout.uvue 中做调度,原因是这里最适合作为全局主内容层。

当前调度职责包括:

  • 首次进入时准备结果
  • 避开隐私说明弹窗
  • 避开更新弹窗
  • 避开公告弹窗
  • 在不冲突时显示 VPN 提示
  • 在 App 回前台时做再检测

第五步:在 App 生命周期里发出前台事件

本项目在 App.uvueonShow 中发出前台事件,代码思路如下:

uni.$emit(VPN_NOTICE_APP_FOREGROUND_EVENT)

这样布局页无需直接依赖 App 生命周期,也方便后续扩展成更多前台恢复逻辑。

第六步:在设置页提供手动控制入口

本项目在 pages/tabs/more/settings/settings.uvue 中提供了 3 个能力:

  • 总开关:是否自动提示 VPN 环境
  • 会话恢复:恢复本次启动提醒
  • 手动检测:立即检测当前 VPN 状态

9. 示例:本项目中的典型调用方式

9.1 启动时准备 VPN 检测结果

this.pendingVpnPrompt = shouldShowVpnNotice(getVpnEnabledAtLaunch())

作用:

  • 只在启动阶段检测一次
  • 自动考虑“是否已关闭提示”“本次启动是否已免打扰”

9.2 前台恢复时再次检测

const currentVpnEnabled = detectCurrentVpnEnabled()
if (shouldShowVpnNotice(currentVpnEnabled) == true) {
    this.vpnPromptVisible = true
    this.startVpnPromptCountdown()
}

作用:

  • 用户切到系统设置打开/关闭 VPN 后,再回到 App 能立即反映最新状态

9.3 设置页即时检测

checkCurrentVpnState() {
    const vpnEnabled = detectCurrentVpnEnabled()
    if (vpnEnabled) {
        this.showNotice('检测结果:当前处于 VPN 网络环境', 'error')
        return
    }
    this.showNotice('检测结果:当前未发现 VPN 网络环境', 'success')
}

作用:

  • 给开发者、测试人员、运维演示时快速验证插件是否正常工作

10. 常见问题

10.1 为什么 Web 总是返回 false

因为 Web 环境没有统一、可靠的浏览器级原生 VPN 状态 API。

10.2 为什么 iOS 检测不是 100% 准确?

因为 iOS 不向普通应用公开稳定、统一的“当前系统 VPN 已开启”接口,本插件采用的是公开 API 范围内较常见的启发式实现。

10.3 为什么建议把插件能力再包一层 utils/vpn-notice.uts

因为原始插件只负责“检测”,而业务真正需要的是:

  • 是否显示
  • 什么时候显示
  • 是否本次启动免打扰
  • 是否在前台恢复时再次检测

这些都属于业务层逻辑,不适合直接写进插件本体。

10.4 可以只保留插件,不要浮窗和设置页吗?

可以。插件是独立可用的,浮窗和设置页只是本项目给出的完整接入示例。

11. FAQ 排障清单

这一节用于回答开发者最常遇到的问题,方便排查“为什么检测结果和预期不一致”。

11.1 为什么 iOS 检测不到 VPN?

可能原因:

  • 当前 iOS 实现是启发式判断,不是 Apple 官方公开的绝对 VPN 状态接口
  • 你当前使用的 VPN 产品没有暴露 utuntaptunpppipsec 这类常见接口名前缀
  • 设备当前网络状态变化较快,而你的页面没有在合适时机重新触发检测

建议排查:

  • 先确认是在真机环境验证,而不是只看静态代码逻辑
  • 尝试切换不同 VPN 应用或不同连接模式再测试
  • 确认是否在 App 回前台或手动点击“立即检测当前 VPN 状态”后重新获取结果

11.2 为什么 Web 永远是 false

原因很简单:

  • 浏览器环境没有统一、可靠、公开的 VPN 状态 API
  • 本插件在 Web 端的设计目标是“保证可编译、可调用、行为明确”,而不是伪造一个不可靠的检测结果

因此:

  • Web 端固定返回 false 是设计行为,不是 bug
  • 如果你要在 Web 端给用户做网络风险提示,需要另外设计业务层启发式方案

11.3 为什么只建议做提示,不建议做阻断?

原因如下:

  • Android 虽然相对可靠,但本质仍然是网络环境判断,不代表业务请求一定失败
  • iOS 是启发式检测,天然存在漏报和误报可能
  • Web 和未实现平台没有真实检测能力

所以更合理的使用方式是:

  • 用它提醒用户“VPN 可能影响服务连接”
  • 引导用户在加载失败时关闭 VPN 重试
  • 不要直接因为 isVpnEnabled() == true 就拒绝用户进入核心业务流程

11.4 为什么某些平台可以调用,但不代表支持真实检测?

这是因为插件分成两个层次:

  • 第一层是“接口可用”:项目能正常 import、编译、运行
  • 第二层是“能力真实”:平台确实有有效检测逻辑

例如:

  • Web 可以调用,但返回固定 false
  • 其他未实现平台可以调用,但依赖兜底实现,返回固定 false
  • Android / iOS 才是当前真正有检测逻辑的平台

11.5 为什么我开着 VPN,但 Android 没提示?

建议检查:

  • 当前 VPN 是否真的接管了系统活动网络
  • 是否在连接完成前就提前调用了检测方法
  • 是否被业务层的“本次启动不再提示”或“总开关关闭”状态拦截了浮窗显示

快速验证方法:

  • 打开设置页的“立即检测当前 VPN 状态”按钮直接测试
  • 恢复“本次启动提醒”后再切到后台、重新回前台验证二次检测

11.6 为什么我开着 VPN,但浮窗没出现?

这不一定是插件问题,也可能是业务层调度问题。

请检查:

  • 是否已关闭设置页中的“VPN 环境提示”总开关
  • 是否已经点过“本次启动不再提示”
  • 当前是否被隐私说明弹窗、更新弹窗、公告弹窗等遮罩拦住
  • 当前页面是否真的走到了 layout.uvue 中的显示调度逻辑

11.7 为什么只做一次启动检测还不够?

因为用户可能在以下场景改变 VPN 状态:

  • 启动 App 后切到系统设置打开 VPN
  • 启动 App 后切到其他 VPN 应用连接/断开 VPN
  • 页面停留时间较长,期间网络环境已变化

所以本项目才额外补了“前后台切回时二次检测”与“设置页手动检测入口”。

12. 维护建议

  • 如果后续要支持更多平台,优先在 utssdk 下增加对应平台目录实现
  • 如果 iOS 后续出现更稳定的公开 API,可以只替换 Mech1VpnDetectorNative.swift
  • 如果要扩展更多网络环境识别能力,例如代理、蜂窝、弱网、内网环境,建议继续沿用“插件负责检测、业务层负责调度”的架构

13. 更新日志

13.1 v1.0.0

当前版本:1.0.0

本版本为首个项目内可用版本,已经包含以下能力:

  • 新增 isVpnEnabled() 同步检测 API
  • 新增 Android 原生 VPN 检测实现,基于 ConnectivityManagerNetworkCapabilities.TRANSPORT_VPN
  • 新增 iOS 启发式 VPN 检测实现,基于 CFNetworkCopySystemProxySettings() 与网络接口名前缀匹配
  • 新增 Web 与默认平台兜底实现,统一返回 false
  • 完成项目侧启动检测、前后台切回二次检测、提示浮窗、会话免打扰、设置页总开关、手动检测入口等完整接入

如果后续插件逻辑有变化,建议同时更新:

  • uni_modules/mech1-vpn-detector/package.json
  • uni_modules/mech1-vpn-detector/CHANGELOG.md
  • uni_modules/mech1-vpn-detector/readme.md

14. 已知限制

在正式用于业务前,建议开发者先了解这些限制:

14.1 Android 限制

  • 当前实现以“当前活动网络”作为判断基础,如果系统存在复杂多网络并行场景,本插件只关注当前活动网络是否带有 VPN 传输能力
  • 插件设计目标是“业务提醒”,不是“强风控阻断”;如果你的业务要求更严格的网络审计,需要结合更多系统信号

14.2 iOS 限制

  • iOS 方案为启发式检测,不是 Apple 官方提供的“绝对准确 VPN 状态 API”
  • 某些 VPN 软件可能不会暴露常见接口名前缀,导致漏报
  • 某些特殊网络代理或企业网络环境,理论上存在误报可能
  • 因此 iOS 结果更适合提示用户“当前网络可能影响访问”,不建议直接作为安全判定依据

14.3 Web 限制

  • Web 端没有统一可靠的浏览器级 VPN 状态接口
  • 因此本插件在 Web 端固定返回 false
  • 如果你希望在 Web 端做网络风险提示,需要考虑其他业务层启发式手段,而不是依赖本插件

14.4 跨平台限制

  • 当前插件 API 只有一个同步布尔返回值,不包含 VPN 类型、连接来源、代理详情等高级信息
  • 当前插件不提供事件监听;若 VPN 状态发生变化,需要业务层自己选择合适时机再次调用
  • 当前插件不负责 UI,不负责提示文案,不负责会话状态管理,这些能力应由业务层封装

15. 后续规划

以下是推荐的插件演进方向,便于后续维护或二次开发:

15.1 短期规划

  • 增加更清晰的错误与状态表达,例如区分“不支持检测”“未检测到 VPN”“检测失败”
  • 补充独立的 CHANGELOG.md 版本维护规范
  • 补充更多开发态示例,例如设置页测试入口、启动检测模板、前后台恢复模板

15.2 中期规划

  • 增加更多平台支持,例如小程序侧的兜底策略说明或平台特化实现
  • 增加更丰富的网络环境检测能力,例如代理、弱网、网络切换、证书异常前置感知
  • 将当前项目中的 utils/vpn-notice.uts 抽象成更通用的业务封装模板

15.3 长期规划

  • 如果 iOS 后续出现更稳定、更公开的官方 API,可替换当前启发式实现
  • 如果业务需要更强的联网诊断能力,可以扩展为“网络环境诊断插件”,将 VPN、代理、DNS、网络可达性统一纳入一套检测体系

16. 相关文件索引

16.1 插件本体

  • uni_modules/mech1-vpn-detector/package.json
  • uni_modules/mech1-vpn-detector/CHANGELOG.md
  • uni_modules/mech1-vpn-detector/readme.md
  • uni_modules/mech1-vpn-detector/utssdk/interface.uts
  • uni_modules/mech1-vpn-detector/utssdk/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/web/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-android/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-vpn-detector/utssdk/app-ios/Mech1VpnDetectorNative.swift

16.2 项目内业务接入示例

  • utils/vpn-notice.uts
  • components/common/VpnNoticePopup.uvue
  • pages/tabs/layout.uvue
  • pages/tabs/more/settings/settings.uvue
  • App.uvue

平台兼容性

uni-app x(3.7.1)

Chrome Safari Android iOS 鸿蒙 微信小程序
-

mech1-***-detector

mech1-***-detector 是一个用于 uni-app x 项目的 UTS API 插件,用来检测当前设备网络是否处于 *** 环境。

插件信息卡片

项目 内容
插件名称 mech1-***-detector
当前版本 1.0.0
最近更新时间 2026-03-23
插件定位 uni-app x App 侧 *** 网络环境检测插件
插件类型 UTS API 插件
核心能力 同步检测 ***、支持 Android/iOS、支持项目级二次封装
适用场景 启动提示、回前台复检、设置页手动检测、网络异常排障引导
真实检测平台 Android、iOS
可编译调用平台 Android、iOS、Web、未单独实现平台兜底
当前 HBuilderX 要求 建议使用 3.1.0+ 以支持 uni_modules;当前项目验证环境为 5.04.2026031906-alpha

核心能力速览

  • 提供同步 API is***Enabled(): boolean
  • Android 基于 ConnectivityManager / NetworkCapabilities.TRANSPORT_*** 判断
  • iOS 基于 CFNetworkCopySystemProxySettings() 做启发式判断
  • Web 与未实现平台可编译、可调用,但默认返回 false
  • 易于接入启动检测、前后台切回检测、设置页测试入口等业务场景

安装与接入

这一节按更接近插件市场发布页的方式整理,方便开发者快速完成导入、调用和验证。

1. 安装方式

你可以用以下任一方式接入:

方式 A:直接使用当前项目中的现成插件目录

本项目已经包含插件目录:

uni_modules/mech1-***-detector

如果你是在本项目内开发,通常不需要额外安装。

方式 B:复制到其他 uni-app x 项目

将以下目录整体复制到目标项目:

uni_modules/mech1-***-detector

复制后建议重新打开 HBuilderX 或重新编译一次工程,让 uni_modules 索引刷新。

2. 导入方式

.uvue.uts 中按插件根目录导入,不要直接导入平台实现文件:

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

推荐做法:

  • 从插件根目录导入
  • 通过业务层工具函数二次封装后再在页面使用

不推荐做法:

import { is***Enabled } from '@/uni_modules/mech1-***-detector/utssdk/app-android/index.uts'

3. 最小 HBuilderX 要求

参考 uni_modules 规范与 DCloud 插件市场常见要求,建议如下:

  • uni_modules 机制建议使用 HBuilderX 3.1.0+
  • 本插件用于 uni-app x,建议使用较新的 uni-app x / HBuilderX 版本
  • 当前项目实际验证环境:HBuilderX 5.04.2026031906-alpha

如果你在较旧版本 HBuilderX 中遇到以下问题:

  • uni_modules 无法识别
  • UTS 插件类型提示异常
  • 平台入口文件没有正确索引

优先建议升级 HBuilderX 后再验证。

4. 推荐验证步骤

为了更接近真实发布页里的“快速验证”,建议开发者按下面顺序完成验证。

4.1 基础调用验证

在任意页面或工具文件中加入:

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

const ***Enabled = is***Enabled()
console.log('***Enabled =', ***Enabled)

验证目标:

  • 工程能正常编译
  • 调用无报错
  • 能获得布尔值结果

4.2 Android 真机验证

建议步骤:

  1. 关闭 ***,进入页面调用一次,确认返回 false
  2. 打开系统 App,等待连接完成
  3. 再次调用 is***Enabled(),确认返回 true
  4. 如项目已接入设置页检测按钮,可直接点“立即检测当前 *** 状态”验证

4.3 iOS 真机验证

建议步骤:

  1. 关闭 ***,调用一次,确认返回 false
  2. 打开 *** 后重新进入页面、切回前台,或手动点检测按钮
  3. 观察是否命中启发式检测结果

注意:

  • iOS 可能因不同 *** 产品实现差异而出现漏报或误报
  • 建议用多种 *** 连接模式交叉验证

4.4 Web 验证

Web 端验证重点不是“能否检测出 ***”,而是:

  • 工程是否能正常编译
  • 调用是否安全
  • 返回值是否稳定为 false

4.5 项目级完整接入验证

如果你采用本项目完整接入方案,建议额外验证:

  1. 启动时是否按预期弹出提示
  2. 点击“本次启动不再提示”后,本轮启动是否静默
  3. 设置页总开关关闭后,是否不再弹窗
  4. 切到后台再回前台后,是否会根据当前 *** 状态重新检测
  5. 设置页“立即检测当前 *** 状态”是否能即时反馈结果

本插件当前已在本项目中完成以下接入能力:

  • App 启动时检测 *** 环境
  • App 从后台切回前台时二次检测 *** 环境
  • 配合浮窗组件提示用户当前网络可能影响服务连接
  • 支持“本次启动不再提示”
  • 支持设置页总开关
  • 支持设置页手动测试当前 *** 状态

如果你是第一次接触本插件,建议按下面顺序阅读:

  1. 先看“插件能力概览”
  2. 再看“快速开始”
  3. 再看“完整接入方案”
  4. 最后看“文件结构与每个文件的作用”

1. 插件能力概览

1.1 对外 API

本插件当前只对外暴露 1 个同步方法:

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

const ***Enabled = is***Enabled()

返回值:

  • true:当前检测到设备处于 *** 环境
  • false:当前未检测到 *** 环境,或当前平台不支持检测

1.2 平台行为

平台 实现方式 返回结果说明
Android 通过 ConnectivityManager + NetworkCapabilities.TRANSPORT_*** 判断当前活动网络 准确度较高,适合业务提示与运行时检测
iOS 通过 CFNetworkCopySystemProxySettings() 读取系统网络作用域接口名,并匹配 utuntaptunpppipsec 等前缀 启发式判断,适合风险提示,不建议当作强安全校验
Web 直接返回 false Web 不提供原生 *** 状态判断能力
其他未单独实现平台 通过根入口兜底返回 false 避免跨端编译报错

1.3 平台兼容性

参考 DCloud 插件市场常见展示方式,这里补充一份更直观的平台兼容性说明,便于开发者像查看 hans-blur-viewlime-transition 一样快速判断可用范围。

1.3.1 插件本体兼容性

平台 是否支持 说明
Android 原生检测,基于当前活动网络能力判断
iOS 启发式检测,基于系统网络作用域接口名判断
鸿蒙 - 当前未实现专用平台入口,默认走兜底返回 false
Web Chrome 可编译可调用,但检测结果固定为 false
Web Safari 可编译可调用,但检测结果固定为 false
微信小程序 可编译可调用,但当前无专用实现,默认返回 false
其他未单独实现平台 utssdk/index.uts 兜底,统一返回 false

1.3.2 项目内完整接入链路兼容性

能力 Android iOS 鸿蒙 Web
is***Enabled() 插件调用 -
返回真实 *** 检测结果 - -
启动时自动检测 - -
前后台切回二次检测 - -
毛玻璃风险浮窗 取决于项目 UI 方案 √(模拟毛玻璃)
设置页总开关 取决于项目接入
设置页手动检测按钮 取决于项目接入 √(结果固定未检测到)

1.3.3 与常见插件市场展示风格的对应关系

  • 类似 hans-blur-view:会强调“平台兼容性 + 运行效果差异 + 标准基座/自定义基座限制”
  • 类似 lime-transition:会强调“哪些平台可编译、哪些平台可运行、哪些平台行为一致或退化”
  • 对于 mech1-***-detector,最重要的不是“能不能编译”,而是“返回值是否真实有效”
  • 因此阅读兼容性时,要区分“支持编译调用”和“支持真实检测”这两个层次

1.4 适用场景

  • 在 App 启动后提醒用户当前网络可能影响访问
  • 在 WebView / 内嵌网页 / 接口访问异常时,给出“请关闭 *** 后重试”的引导
  • 在设置页中提供网络环境自检能力
  • 在前后台切换时做轻量级网络状态复查

2. 快速开始

2.1 目录位置

插件位于:

uni_modules/mech1-***-detector

根据 uni-app x UTS 插件规范,插件的核心目录是 utssdk。官方文档中明确说明:

  • interface.uts 用于“声明插件对外暴露的 API,必需”
  • 分平台目录如 app-android/index.utsapp-ios/index.utsweb/index.uts 用于各平台具体实现
  • 当根目录和平台目录同时存在时,优先使用平台目录实现

2.2 最简单调用方式

在任意 .uvue / .uts 文件中直接引入:

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

const ***Enabled = is***Enabled()
if (***Enabled) {
    uni.showToast({
        title: '当前处于 *** 网络环境',
        icon: 'none'
    })
}

2.3 推荐调用时机

建议在以下节点调用:

  • App 首次进入主页面后
  • 用户从后台切回前台时
  • 打开依赖网络的关键页面前
  • 设置页手动检测按钮点击时

不建议高频轮询调用。

3. 完整接入方案

本项目已经做了一套完整接入,你可以直接复用。

3.1 项目内现有接入链路

A. 插件底层检测

文件:uni_modules/mech1-***-detector/utssdk/app-android/index.uts

  • Android 直接读取当前活动网络能力
  • 如果活动网络包含 TRANSPORT_***,返回 true

文件:uni_modules/mech1-***-detector/utssdk/app-ios/index.uts

  • iOS 调用 Swift 混编类 Mech1***DetectorNative
  • Swift 侧使用 CFNetwork 公开 API 进行启发式判断

B. 项目级状态管理

文件:utils/***-notice.uts

这个文件不是插件本体,但它是项目接入插件时最关键的一层封装,负责:

  • 统一读取插件检测结果
  • 管理“是否开启 *** 提示”的持久化配置
  • 管理“本次启动不再提示”的会话级状态
  • 管理 App 前后台切换时触发的检测事件

C. UI 提示浮窗

文件:components/common/***NoticePopup.uvue

负责显示:

  • 渐变毛玻璃提示卡片
  • 5 秒自动关闭倒计时
  • 手动关闭按钮
  • “本次启动不再提示”按钮

D. 页面联动入口

文件:pages/tabs/layout.uvue

负责:

  • 页面首次进入时准备 *** 检测结果
  • 避开隐私说明、更新提示、公告提示等遮罩冲突
  • 在合适时机显示 *** 浮窗
  • App 回到前台时执行二次检测

E. App 前后台事件转发

文件:App.uvue

负责:

  • onShow 中发出 ***_NOTICE_APP_FOREGROUND_EVENT
  • 通知布局页进行“回前台后的二次检测”

F. 设置页控制入口

文件:pages/tabs/more/settings/settings.uvue

负责:

  • 控制总开关“*** 环境提示”
  • 显示“本次启动状态”
  • 提供“恢复本次启动提醒”按钮
  • 提供“立即检测当前 *** 状态”测试入口

4. 插件 API 文档

4.1 is***Enabled(): boolean

定义文件:uni_modules/mech1-***-detector/utssdk/interface.uts

源码如下:

export type Is***Enabled = () => boolean

实现导出名称:

export const is***Enabled: Is***Enabled = function (): boolean {
    ...
}

参数

无。

返回值

  • true:检测到 ***
  • false:未检测到 ***,或当前平台不支持

特点

  • 同步调用
  • 零配置
  • 适合页面逻辑中直接判断
  • 适合再次封装到项目级工具中统一管理

5. 各平台实现说明

5.1 Android 实现说明

文件:uni_modules/mech1-***-detector/utssdk/app-android/index.uts

当前实现逻辑:

  1. 通过 UTSAndroid.getAppContext() 获取应用上下文
  2. 通过 Context.CONNECTIVITY_SERVICE 获取 ConnectivityManager
  3. 读取当前 activeNetwork
  4. 通过 getNetworkCapabilities(activeNetwork) 获取网络能力
  5. 调用 hasTransport(NetworkCapabilities.TRANSPORT_***) 判断是否为 *** 网络

核心代码示例:

const activeNetwork = connectivityManager.getActiveNetwork()
if (activeNetwork == null) {
    return false
}

const capabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
if (capabilities == null) {
    return false
}

return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_***) == true

为什么 Android 端没有用 Kotlin 混编?

因为这部分系统 API 逻辑足够简单,直接纯 UTS 即可完成,维护成本更低,编译链更简单。

5.2 iOS 实现说明

文件:

  • uni_modules/mech1-***-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-ios/Mech1***DetectorNative.swift

iOS 没有像 Android 一样通用、稳定、面向普通应用的公开 API 来直接返回“当前是否启用 ***”。

因此当前实现采用启发式方案:

  1. 通过 CFNetworkCopySystemProxySettings() 获取系统网络代理配置
  2. 读取 kCFNetworkProxiesScoped 对应的网络接口集合
  3. 检查接口名是否存在典型 *** 虚拟网卡前缀,如:
    • utun
    • tap
    • tun
    • ppp
    • ipsec

核心 Swift 逻辑示例:

guard let scoped = proxySettings[kCFNetworkProxiesScoped as String] as? NSDictionary else {
    return false
}

let keys = scoped.allKeys.compactMap { $0 as? String }
for key in keys {
    let lowercasedKey = key.lowercased()
    for prefix in ***InterfacePrefixes {
        if lowercasedKey.hasPrefix(prefix) {
            return true
        }
    }
}

iOS 方案局限性

这很重要,开发者必须明确:

  • 这是启发式判断,不是绝对准确的系统级事实判断
  • 适合做 UI 提示、风险提醒、排障辅助
  • 不适合做强风控、强安全校验、强业务阻断
  • 某些 *** 可能漏报
  • 某些特殊网络环境可能误报

5.3 Web 与其他平台实现说明

文件:

  • uni_modules/mech1-***-detector/utssdk/index.uts
  • uni_modules/mech1-***-detector/utssdk/web/index.uts

这两个文件统一返回 false,用于:

  • 保证 Web 编译通过
  • 保证其他未实现平台不会报错
  • 明确插件当前主要服务于 App 端

6. 文件结构与每个文件的作用

插件目录结构如下:

uni_modules/
└─ mech1-***-detector/
   ├─ package.json
   ├─ readme.md
   └─ utssdk/
      ├─ interface.uts
      ├─ index.uts
      ├─ web/
      │  └─ index.uts
      ├─ app-android/
      │  └─ index.uts
      └─ app-ios/
         ├─ index.uts
         └─ Mech1***DetectorNative.swift

下面是每个文件的职责说明。

6.1 package.json

路径:uni_modules/mech1-***-detector/package.json

作用:

  • 声明插件 ID、名称、版本、描述
  • 让 uni_modules 正确识别该插件
  • 作为插件发布与依赖识别的基础元数据文件

6.2 readme.md

路径:uni_modules/mech1-***-detector/readme.md

作用:

  • 说明插件怎么用
  • 解释每个平台的实现差异
  • 帮助项目开发者快速接入或二次维护

6.3 utssdk/interface.uts

路径:uni_modules/mech1-***-detector/utssdk/interface.uts

作用:

  • 定义插件对外暴露的类型签名
  • 让 HBuilderX 为调用方提供类型提示
  • 作为“声明层”,与各平台 index.uts 对应

6.4 utssdk/index.uts

路径:uni_modules/mech1-***-detector/utssdk/index.uts

作用:

  • 作为非 App / 未单独实现平台的兜底入口
  • 默认返回 false
  • 避免平台缺失实现时报错

6.5 utssdk/web/index.uts

路径:uni_modules/mech1-***-detector/utssdk/web/index.uts

作用:

  • 明确 Web 平台行为
  • 统一返回 false
  • 让 Web 端编译表现更明确、更易理解

6.6 utssdk/app-android/index.uts

路径:uni_modules/mech1-***-detector/utssdk/app-android/index.uts

作用:

  • Android 平台的核心检测实现
  • 直接操作 Android 系统网络能力 API
  • 不依赖 Kotlin 混编

6.7 utssdk/app-ios/index.uts

路径:uni_modules/mech1-***-detector/utssdk/app-ios/index.uts

作用:

  • iOS 平台的 UTS 入口
  • 负责桥接到 Swift 混编类

6.8 utssdk/app-ios/Mech1***DetectorNative.swift

路径:uni_modules/mech1-***-detector/utssdk/app-ios/Mech1***DetectorNative.swift

作用:

  • iOS 平台原生混编实现
  • 使用 FoundationCFNetwork 进行启发式检测
  • 暴露 Mech1***DetectorNative.is***Enabled() 给 UTS 调用

7. 在项目中单独使用插件

如果你不需要本项目现有的浮窗、设置页、会话状态管理,只想单独使用插件做一次检测,可以这样写。

7.1 在页面中直接调用

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

export default {
    onShow() {
        const ***Enabled = is***Enabled()
        if (***Enabled) {
            uni.showToast({
                title: '检测到 *** 网络环境',
                icon: 'none'
            })
        }
    }
}

7.2 在工具函数中封装

import { is***Enabled } from '@/uni_modules/mech1-***-detector'

export function check***AndNotify(): boolean {
    const enabled = is***Enabled() == true
    if (enabled) {
        uni.showToast({
            title: '当前网络处于 *** 环境',
            icon: 'none'
        })
    }
    return enabled
}

8. 本项目完整使用教程

如果你想按本项目现有方式完整接入,请按下面步骤理解。

第一步:保留插件本体

确保以下文件存在:

  • uni_modules/mech1-***-detector/package.json
  • uni_modules/mech1-***-detector/utssdk/interface.uts
  • uni_modules/mech1-***-detector/utssdk/app-android/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-ios/Mech1***DetectorNative.swift

第二步:增加项目级状态封装

项目使用的是 utils/***-notice.uts 这一层封装,而不是在页面里到处直接调用插件。

这样做的好处:

  • 页面层更干净
  • 提示开关可统一管理
  • 会话免打扰可统一管理
  • 回前台二次检测逻辑只写一次

第三步:增加提示浮窗 UI

components/common/***NoticePopup.uvue 中维护统一样式与交互。

这样做的好处:

  • UI 统一
  • 可以单独演进视觉效果
  • 页面里只处理显示时机,不关心具体样式细节

第四步:在主布局页做显示调度

本项目在 pages/tabs/layout.uvue 中做调度,原因是这里最适合作为全局主内容层。

当前调度职责包括:

  • 首次进入时准备结果
  • 避开隐私说明弹窗
  • 避开更新弹窗
  • 避开公告弹窗
  • 在不冲突时显示 *** 提示
  • 在 App 回前台时做再检测

第五步:在 App 生命周期里发出前台事件

本项目在 App.uvueonShow 中发出前台事件,代码思路如下:

uni.$emit(***_NOTICE_APP_FOREGROUND_EVENT)

这样布局页无需直接依赖 App 生命周期,也方便后续扩展成更多前台恢复逻辑。

第六步:在设置页提供手动控制入口

本项目在 pages/tabs/more/settings/settings.uvue 中提供了 3 个能力:

  • 总开关:是否自动提示 *** 环境
  • 会话恢复:恢复本次启动提醒
  • 手动检测:立即检测当前 *** 状态

9. 示例:本项目中的典型调用方式

9.1 启动时准备 *** 检测结果

this.pending***Prompt = shouldShow***Notice(get***EnabledAtLaunch())

作用:

  • 只在启动阶段检测一次
  • 自动考虑“是否已关闭提示”“本次启动是否已免打扰”

9.2 前台恢复时再次检测

const current***Enabled = detectCurrent***Enabled()
if (shouldShow***Notice(current***Enabled) == true) {
    this.***PromptVisible = true
    this.start***PromptCountdown()
}

作用:

  • 用户切到系统设置打开/关闭 *** 后,再回到 App 能立即反映最新状态

9.3 设置页即时检测

checkCurrent***State() {
    const ***Enabled = detectCurrent***Enabled()
    if (***Enabled) {
        this.showNotice('检测结果:当前处于 *** 网络环境', 'error')
        return
    }
    this.showNotice('检测结果:当前未发现 *** 网络环境', 'success')
}

作用:

  • 给开发者、测试人员、运维演示时快速验证插件是否正常工作

10. 常见问题

10.1 为什么 Web 总是返回 false

因为 Web 环境没有统一、可靠的浏览器级原生 *** 状态 API。

10.2 为什么 iOS 检测不是 100% 准确?

因为 iOS 不向普通应用公开稳定、统一的“当前系统 *** 已开启”接口,本插件采用的是公开 API 范围内较常见的启发式实现。

10.3 为什么建议把插件能力再包一层 utils/***-notice.uts

因为原始插件只负责“检测”,而业务真正需要的是:

  • 是否显示
  • 什么时候显示
  • 是否本次启动免打扰
  • 是否在前台恢复时再次检测

这些都属于业务层逻辑,不适合直接写进插件本体。

10.4 可以只保留插件,不要浮窗和设置页吗?

可以。插件是独立可用的,浮窗和设置页只是本项目给出的完整接入示例。

11. FAQ 排障清单

这一节用于回答开发者最常遇到的问题,方便排查“为什么检测结果和预期不一致”。

11.1 为什么 iOS 检测不到 ***?

可能原因:

  • 当前 iOS 实现是启发式判断,不是 Apple 官方公开的绝对 *** 状态接口
  • 你当前使用的 *** 产品没有暴露 utuntaptunpppipsec 这类常见接口名前缀
  • 设备当前网络状态变化较快,而你的页面没有在合适时机重新触发检测

建议排查:

  • 先确认是在真机环境验证,而不是只看静态代码逻辑
  • 尝试切换不同 *** 应用或不同连接模式再测试
  • 确认是否在 App 回前台或手动点击“立即检测当前 *** 状态”后重新获取结果

11.2 为什么 Web 永远是 false

原因很简单:

  • 浏览器环境没有统一、可靠、公开的 *** 状态 API
  • 本插件在 Web 端的设计目标是“保证可编译、可调用、行为明确”,而不是伪造一个不可靠的检测结果

因此:

  • Web 端固定返回 false 是设计行为,不是 bug
  • 如果你要在 Web 端给用户做网络风险提示,需要另外设计业务层启发式方案

11.3 为什么只建议做提示,不建议做阻断?

原因如下:

  • Android 虽然相对可靠,但本质仍然是网络环境判断,不代表业务请求一定失败
  • iOS 是启发式检测,天然存在漏报和误报可能
  • Web 和未实现平台没有真实检测能力

所以更合理的使用方式是:

  • 用它提醒用户“*** 可能影响服务连接”
  • 引导用户在加载失败时关闭 *** 重试
  • 不要直接因为 is***Enabled() == true 就拒绝用户进入核心业务流程

11.4 为什么某些平台可以调用,但不代表支持真实检测?

这是因为插件分成两个层次:

  • 第一层是“接口可用”:项目能正常 import、编译、运行
  • 第二层是“能力真实”:平台确实有有效检测逻辑

例如:

  • Web 可以调用,但返回固定 false
  • 其他未实现平台可以调用,但依赖兜底实现,返回固定 false
  • Android / iOS 才是当前真正有检测逻辑的平台

11.5 为什么我开着 ***,但 Android 没提示?

建议检查:

  • 当前 *** 是否真的接管了系统活动网络
  • 是否在连接完成前就提前调用了检测方法
  • 是否被业务层的“本次启动不再提示”或“总开关关闭”状态拦截了浮窗显示

快速验证方法:

  • 打开设置页的“立即检测当前 *** 状态”按钮直接测试
  • 恢复“本次启动提醒”后再切到后台、重新回前台验证二次检测

11.6 为什么我开着 ***,但浮窗没出现?

这不一定是插件问题,也可能是业务层调度问题。

请检查:

  • 是否已关闭设置页中的“*** 环境提示”总开关
  • 是否已经点过“本次启动不再提示”
  • 当前是否被隐私说明弹窗、更新弹窗、公告弹窗等遮罩拦住
  • 当前页面是否真的走到了 layout.uvue 中的显示调度逻辑

11.7 为什么只做一次启动检测还不够?

因为用户可能在以下场景改变 *** 状态:

  • 启动 App 后切到系统设置打开 ***
  • 启动 App 后切到其他 应用连接/断开
  • 页面停留时间较长,期间网络环境已变化

所以本项目才额外补了“前后台切回时二次检测”与“设置页手动检测入口”。

12. 维护建议

  • 如果后续要支持更多平台,优先在 utssdk 下增加对应平台目录实现
  • 如果 iOS 后续出现更稳定的公开 API,可以只替换 Mech1***DetectorNative.swift
  • 如果要扩展更多网络环境识别能力,例如代理、蜂窝、弱网、内网环境,建议继续沿用“插件负责检测、业务层负责调度”的架构

13. 更新日志

13.1 v1.0.0

当前版本:1.0.0

本版本为首个项目内可用版本,已经包含以下能力:

  • 新增 is***Enabled() 同步检测 API
  • 新增 Android 原生 检测实现,基于 ConnectivityManager 与 `NetworkCapabilities.TRANSPORT_`
  • 新增 iOS 启发式 *** 检测实现,基于 CFNetworkCopySystemProxySettings() 与网络接口名前缀匹配
  • 新增 Web 与默认平台兜底实现,统一返回 false
  • 完成项目侧启动检测、前后台切回二次检测、提示浮窗、会话免打扰、设置页总开关、手动检测入口等完整接入

如果后续插件逻辑有变化,建议同时更新:

  • uni_modules/mech1-***-detector/package.json
  • uni_modules/mech1-***-detector/CHANGELOG.md
  • uni_modules/mech1-***-detector/readme.md

14. 已知限制

在正式用于业务前,建议开发者先了解这些限制:

14.1 Android 限制

  • 当前实现以“当前活动网络”作为判断基础,如果系统存在复杂多网络并行场景,本插件只关注当前活动网络是否带有 *** 传输能力
  • 插件设计目标是“业务提醒”,不是“强风控阻断”;如果你的业务要求更严格的网络审计,需要结合更多系统信号

14.2 iOS 限制

  • iOS 方案为启发式检测,不是 Apple 官方提供的“绝对准确 *** 状态 API”
  • 某些 *** 软件可能不会暴露常见接口名前缀,导致漏报
  • 某些特殊网络代理或企业网络环境,理论上存在误报可能
  • 因此 iOS 结果更适合提示用户“当前网络可能影响访问”,不建议直接作为安全判定依据

14.3 Web 限制

  • Web 端没有统一可靠的浏览器级 *** 状态接口
  • 因此本插件在 Web 端固定返回 false
  • 如果你希望在 Web 端做网络风险提示,需要考虑其他业务层启发式手段,而不是依赖本插件

14.4 跨平台限制

  • 当前插件 API 只有一个同步布尔返回值,不包含 *** 类型、连接来源、代理详情等高级信息
  • 当前插件不提供事件监听;若 *** 状态发生变化,需要业务层自己选择合适时机再次调用
  • 当前插件不负责 UI,不负责提示文案,不负责会话状态管理,这些能力应由业务层封装

15. 后续规划

以下是推荐的插件演进方向,便于后续维护或二次开发:

15.1 短期规划

  • 增加更清晰的错误与状态表达,例如区分“不支持检测”“未检测到 ***”“检测失败”
  • 补充独立的 CHANGELOG.md 版本维护规范
  • 补充更多开发态示例,例如设置页测试入口、启动检测模板、前后台恢复模板

15.2 中期规划

  • 增加更多平台支持,例如小程序侧的兜底策略说明或平台特化实现
  • 增加更丰富的网络环境检测能力,例如代理、弱网、网络切换、证书异常前置感知
  • 将当前项目中的 utils/***-notice.uts 抽象成更通用的业务封装模板

15.3 长期规划

  • 如果 iOS 后续出现更稳定、更公开的官方 API,可替换当前启发式实现
  • 如果业务需要更强的联网诊断能力,可以扩展为“网络环境诊断插件”,将 ***、代理、DNS、网络可达性统一纳入一套检测体系

16. 相关文件索引

16.1 插件本体

  • uni_modules/mech1-***-detector/package.json
  • uni_modules/mech1-***-detector/CHANGELOG.md
  • uni_modules/mech1-***-detector/readme.md
  • uni_modules/mech1-***-detector/utssdk/interface.uts
  • uni_modules/mech1-***-detector/utssdk/index.uts
  • uni_modules/mech1-***-detector/utssdk/web/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-android/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-ios/index.uts
  • uni_modules/mech1-***-detector/utssdk/app-ios/Mech1***DetectorNative.swift

16.2 项目内业务接入示例

  • utils/***-notice.uts
  • components/common/***NoticePopup.uvue
  • pages/tabs/layout.uvue
  • pages/tabs/more/settings/settings.uvue
  • App.uvue

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据,不上传 VPN 检测结果,不内置服务端地址,全部判断逻辑均在本地设备侧完成。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。