更新记录

1.0.0(2026-11-11)

新版发布


平台兼容性

uni-app(5.22)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ × × √ × 5.1 × -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

exam-anti-cheat 考试防作弊 UTS 插件使用说明

面向移动端考试/测评场景的 Android 防作弊 UTS 插件,提供 应用分身检测、前台应用查询(UsageStats)、屏幕固定(LockTask)控制与解除检测、分屏检测、权限引导跳转 五类原子 API,并附带开箱即用的编排层 js_sdk/anti-cheat-monitor.js(轮询、二次确认防误报、违规持久化、强制交卷回调)。

插件只做本地检测,不采集、不上传任何数据;违规上报由接入方通过 reporter 回调自行对接自己的服务端。

一、平台兼容

平台 支持情况
Android(app-android) 完整实现
iOS(app-ios) 安全兜底(iOS 无对等公开 API,详见文末 FAQ)
H5 / 各小程序 安全兜底(调用不报错,返回默认值)

环境要求:

  • HBuilderX 4.75 及以上,Vue3 项目
  • UTS 插件需在 HBuilderX 中制作 自定义基座 后才能在真机生效

二、接入步骤

1. 声明权限(必须)

在 manifest.json → app-plus → distribute → android → permissions 中追加:

"<uses-permission android:name=\"android.permission.PACKAGE_USAGE_STATS\"/>",
"<uses-permission android:name=\"android.permission.QUERY_ALL_PACKAGES\"/>"
  • PACKAGE_USAGE_STATS:不声明则应用 不会出现 在系统「有权查看使用情况的应用」列表中
  • QUERY_ALL_PACKAGES:Android 11+ 包可见性机制下,查询前台应用包名必需

2. 考前准入(进入考试前调用)

import {
  isDualInstance,
  hasUsagePermission,
  openUsageAccessSettings,
  startPin,
} from '@/uni_modules/exam-anti-cheat'

async function admission() {
  return new Promise((resolve) => {
    // ① 应用分身环境:拒绝
    if (isDualInstance()) {
      uni.showModal({ title: '无法考试', content: '检测到应用分身环境,请关闭后重试', showCancel: false })
      return resolve(false)
    }
    // ② 使用情况访问权限:未授权 → 确定后跳系统设置页,返回后复核
    if (!hasUsagePermission()) {
      uni.showModal({
        title: '需要权限',
        content: '参加考试需开启"使用情况访问"权限,点击"确定"前往系统设置开启',
        success: (res) => {
          if (res.confirm) openUsageAccessSettings()
          resolve(false) // 返回后在 onShow 中重新调用 admission() 复核
        },
      })
      return
    }
    // ③ 屏幕固定确认 → 进入考试
    uni.showModal({
      title: '开始考试',
      content: '即将锁定屏幕,考试期间无法使用其他应用,解除锁定将直接交卷',
      success: (res) => {
        if (!res.confirm) return resolve(false)
        startPin()
        resolve(true)
      },
    })
  })
}

3. 考中监测(考试页)

import {
  startMonitoring,
  finishAntiCheat,
  clearViolations,
} from '@/uni_modules/exam-anti-cheat/js_sdk/anti-cheat-monitor.js'

export default {
  onReady() {
    startMonitoring(
      {
        interval: 2500,   // 轮询间隔 ms
        confirmRounds: 2, // AI 命中需连续周期数(二次确认防误报)
        maxViolations: 3, // 累计违规阈值,达到自动交卷
        pinEnabled: true, // 解除固定 = 严重违规,顶格直接交卷
        // AI 应用包名名单,建议服务端下发,失败用本地兜底
        aiPackages: ['com.openai.chatgpt', 'com.deepseek.chat'],
        whitelist: [],    // 白名单包名(输入法、系统 UI 等)
        // 违规上报:接入方自行对接服务端
        reporter: (record) =>
          uni.request({ url: 'https://your.api/exam/violation', method: 'POST', data: record }),
        // 未达顶格的违规提示
        onWarn: ({ count }) =>
          uni.showModal({ title: '警告', content: `检测到异常操作(第 ${count} 次),多次违规将自动交卷`, showCancel: false }),
      },
      ({ type, count }) => {
        // 强制交卷回调:保存答案 → 调交卷接口 → 跳结果页
        console.log('触发强制交卷', type, count)
      },
    )
  },
  onUnload() {
    // 收尾:停监测 → 退固定 → 返回违规记录(补传后 clearViolations() 清空)
    const violations = finishAntiCheat()
    if (violations.length) {
      clearViolations()
    }
  },
}

4. 编排层 API 一览

方法 说明
startMonitoring(cfg, onForceSubmit) 开始监测,配置项见上方示例
stopMonitoring() 停止监测
finishAntiCheat() 收尾:停监测、退固定,返回全部违规记录
getViolations() 读取违规记录(onShow 恢复时以 storage 为准)
clearViolations() 清空违规记录(补传完成后调用)
reportCustomViolation(type, detail) 手动记录业务自定义违规(如前后台切出计数)

三、编排层行为说明

违规类型 触发条件 处理
AI_APP 轮询命中 aiPackages 且连续 confirmRounds 轮 记录 + 计数,达阈值交卷
UNPIN 曾进入固定态后脱离固定 严重违规,顶格直接交卷
MULTI_WINDOW 处于分屏/小窗 记录 + 计数,达阈值交卷

设计关键:非 Device Owner 的屏幕固定在系统层面允许用户手势解除(无法物理禁止),因此本方案将「解除固定」作为最严重违规顶格处理——切分身/切其他应用必须先解除固定,解除的瞬间(不超过 1 个轮询周期)考试即自动结束。解除 = 交卷,效果上等效于完全限制。

四、权限引导页的品牌适配(openUsageAccessSettings)

品牌 行为
vivo 直接打开「有权查看使用情况的应用」列表页(vivo 对深链打开的详情页会禁用开关)
小米 / 华为 / 荣耀 / OPPO / 三星等 带包名直达本应用的开关页
所有品牌(兜底) 直达失败 → 退列表页 → 仍失败 → 应用详情页

五、上线前必测清单

  1. 开启 AI 应用 → 两个轮询周期内出警告(测命中与二次确认)
  2. 固定后做解除手势 → 立即触发强制交卷(测 UNPIN 顶格联动)
  3. 通知栏下拉、输入法切换、锁屏再解锁 → 不产生违规(测误报,重点调 whitelist)
  4. 把 AI 应用放进手机分身使用 → 走到分身必须先解除固定,仍被 UNPIN 抓住(测兜底)
  5. vivo 真机走一遍权限引导:列表中能看到本应用且开关可点击

六、常见问题

Q:应用为什么不出现在「有权查看使用情况的应用」列表里?

未声明 PACKAGE_USAGE_STATS 权限。系统列表只展示声明了该权限的应用,见「接入步骤 1」。

Q:vivo 上权限开关是灰色的?

确认 manifest 已声明权限;若仍置灰,检查系统「健康使用设备 / 原子隐私系统 / 儿童模式」限制,或重启手机。

Q:能彻底禁止用户解除屏幕固定吗?

普通应用不能。只有 Device Owner(adb 预配的考试专用机)可通过 setLockTaskPackages 完全锁死。普通考生手机的标准做法就是本插件的「固定 + 解除即交卷」联动。

Q:iOS 端怎么办?

iOS 无对等公开 API(引导式访问无法被应用控制或检测),插件返回安全默认值。iOS 建议使用 onHide/onShow 前后台切换计数作为基础防作弊手段,与本插件互不影响。

七、隐私与数据声明

  • 插件全部检测逻辑在设备本地完成,不采集任何数据、不发送任何网络请求、无广告
  • 应用自身如需上报违规记录,由接入方通过 reporter 回调自行实现,与插件无关
  • QUERY_ALL_PACKAGES 在国内应用市场分发无政策问题;如上架 Google Play 需按其政策申报用途(考试防作弊)

隐私、权限声明

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

1. android.permission.PACKAGE_USAGE_STATS(使用情况访问权限,由用户在系统设置中授权):用于查询最近前台应用包名,实现考试期间 AI 应用使用检测。 2. android.permission.QUERY_ALL_PACKAGES:Android 11+ 包可见性机制下,识别前台应用包名所必需。

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

插件不采集任何数据,不发送任何网络请求。全部检测逻辑(分身检测、前台应用查询、屏幕固定检测)均在设备本地完成,检测结果由接入方(宿主应用)自行决定如何处理。

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

没有包含

暂无用户评论。