基于安卓的学生签到系统:定位漂移与防代签的完整落地实践
简介这是一套面向高校课程考勤与教学管理场景的安卓学生签到系统完整源码适合计算机相关专业学生做课程设计、毕业设计或安卓与SSM框架练手。项目采用Android Studio开发移动端后端基于SSM框架并在IntelliJ IDEA中搭建支持扫码签到、数字签到、定位签到三种方式签到记录可修改另附加课码选课功能覆盖考勤与选课两大教学管理需求。资源包共3个文件包含2个rar压缩包与1个sql数据库文件分别对应安卓前端工程、后端服务工程和初始数据库脚本整体约139.01MB解压后可直接导入部署。目前已有837人学习下载读者可借此获得一套结构完整、功能可运行的前后端分离项目方案快速理解移动端与SSM后端的接口对接、数据库表设计及签到逻辑实现也可在此基础上二次开发或作为答辩演示素材。1. 基于安卓的学生签到系统从定位漂移到防代签的完整落地思路做过校园信息化的人大多被同一个问题折磨过老师拿着纸质名单挨个点名一节课五分钟没了数据还停留在纸上。基于安卓的学生签到系统要解决的就是这件事——把点名搬到手机端让签到数据实时进库、可统计、可追溯。它适合两类人一类是学校信息化岗的开发者需要一套能跑在普通安卓机上的轻量方案另一类是带课老师或学生干部想自己搭一套不依赖第三方平台的小工具。但真正动手就会发现难点从来不是画个界面点个按钮而是定位漂移、代签、弱网提交失败这三座大山。这篇笔记按我实际踩过的路径从技术选型讲到参数调优把每一步能复现的细节摊开说。2. 技术选型安卓端、服务端和定位方案怎么定2.1 为什么优先选原生安卓而不是跨平台框架标题锁死了基于安卓所以第一件事是确认技术栈。市面上做签到类应用常见三条路原生 AndroidKotlin/Java、跨平台框架Flutter/React Native、以及套壳 WebView。我一般推荐原生理由很实在签到系统重度依赖定位、蓝牙、相机扫码、后台保活这些系统能力跨平台框架在定位精度和后台权限上经常隔一层出问题时排查成本高。原生直接调FusedLocationProviderClient拿到的是系统融合定位结果精度和功耗都可控。服务端不用搞复杂一个 Spring Boot 或 Node.js 的 REST 接口加 MySQL 就够了。核心表就三张课程表、签到任务表、签到记录表。签到记录表里必须存经纬度、定位精度、设备标识、时间戳这几个字段是后面防代签和申诉的依据。提示如果学校已有统一身份认证登录环节直接对接别自己再造一套账号体系否则后期数据对不上是常态。2.2 定位方案GPS、基站、WiFi 三者怎么取舍签到能不能用八成取决于定位准不准。安卓的定位来源有三类GPS卫星、基站蜂窝、WiFi热点。室内教室 GPS 信号弱经常飘到几十米外WiFi 定位在密集教学楼里反而更稳。实际做法是让系统自动融合代码里设置定位优先级为高精度模式同时接受这三种来源。关键参数是签到半径。设太大学生在隔壁楼也能签设太小站在教室后排都签不上。我的经验值是室内 50 到 80 米室外 100 到 150 米。这个值不是拍脑袋要结合定位精度动态判断——如果手机上报的accuracy是 30 米半径却只给 20 米那必然误判。// 请求高精度定位融合 GPS/WiFi/基站 val locationRequest LocationRequest.Builder( Priority.PRIORITY_HIGH_ACCURACY, // 高精度模式 5000L // 5 秒更新一次签到场景够用 ).apply { setMinUpdateDistanceMeters(5f) // 移动 5 米才回调省电 setWaitForAccurateLocation(true) // 等待精度达标再返回 }.build() // 拿到位置后判断是否在签到半径内 fun isInRange( userLat: Double, userLng: Double, userAcc: Float, targetLat: Double, targetLng: Double, radius: Double ): Boolean { val results FloatArray(1) Location.distanceBetween(userLat, userLng, targetLat, targetLng, results) val distance results[0] // 把定位误差算进去避免精度差导致误判 return distance radius userAcc }这段代码有两个要点。第一setWaitForAccurateLocation(true)会让系统多等一会儿拿更准的结果签到场景值得这点延迟。第二判断距离时把userAcc定位精度加进半径这是很多人忽略的地方——手机自己都承认误差 30 米你却按精确点算必然出问题。2.3 服务端接口设计一次签到要传哪些字段接口设计决定了后面能不能防代签。签到请求不能只传学生ID 课程ID那样谁都能伪造。至少要带上经纬度、定位精度、设备唯一标识、客户端时间戳、以及一个服务端下发的动态令牌。-- 签到记录表核心字段 CREATE TABLE sign_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_id BIGINT NOT NULL, student_id BIGINT NOT NULL, sign_time DATETIME NOT NULL, -- 服务端时间不信客户端 latitude DOUBLE, -- 签到纬度 longitude DOUBLE, -- 签到经度 accuracy FLOAT, -- 定位精度米 device_id VARCHAR(64), -- 设备标识防一机多签 token VARCHAR(64), -- 动态令牌防重放 status TINYINT DEFAULT 1, -- 1正常 2异常待审 UNIQUE KEY uk_course_student (course_id, student_id) );sign_time一定要用服务端时间客户端时间可以被改。device_id用来识别同一台设备给多个账号签到的情况。token是老师发起签到时服务端生成的有效期设 2 到 5 分钟过期作废这样截个二维码慢慢传也来不及。3. 动手实现从发起签到到数据落库的完整链路3.1 老师端发起签到动态令牌怎么生成和刷新老师点发起签到服务端做三件事生成一个随机令牌、记录签到开始时间、设定有效期。令牌用 UUID 加时间戳哈希别用自增 ID否则能被猜。// 服务端发起签到生成动态令牌 public String startSign(Long courseId, int validSeconds) { String token UUID.randomUUID().toString().replace(-, ); // 存 Rediskey 带课程维度过期自动失效 String key sign:token: courseId; redisTemplate.opsForValue().set(key, token, validSeconds, TimeUnit.SECONDS); // 同时记录签到开始时间用于判断迟到 redisTemplate.opsForValue().set( sign:start: courseId, String.valueOf(System.currentTimeMillis()), validSeconds, TimeUnit.SECONDS ); return token; }validSeconds我一般设 120 到 300 秒。太短学生来不及操作太长代签空间大。令牌存 Redis 而不是数据库是因为它天然带过期不用自己写清理逻辑。老师端界面把这个令牌转成二维码显示学生扫码后带着令牌提交签到。3.2 学生端签到流程扫码、定位、提交三步学生端流程要顺任何一步卡住都会有人放弃。顺序是扫码拿令牌 → 请求定位 → 组装数据提交。定位这步要加超时和降级不能无限等。// 学生端扫码后执行签到 suspend fun doSign(token: String, courseId: Long): SignResult { // 1. 拿定位最多等 8 秒 val location withTimeoutOrNull(8000L) { getCurrentLocation() } ?: return SignResult.Fail(定位超时请到窗边重试) // 2. 组装请求体 val body mapOf( courseId to courseId, token to token, latitude to location.latitude, longitude to location.longitude, accuracy to location.accuracy, deviceId to getDeviceId() ) // 3. 提交失败进本地队列等重试 return try { val resp api.sign(body) if (resp.code 0) SignResult.Success else SignResult.Fail(resp.msg) } catch (e: IOException) { LocalQueue.enqueue(body) // 弱网兜底 SignResult.Pending(网络异常已缓存待提交) } }withTimeoutOrNull(8000L)是血泪经验——不设超时室内定位偶尔要等半分钟学生以为卡死了就退出重来。8 秒拿不到就提示换位置。弱网时把请求塞进本地队列等网络恢复再补交这是保证签到率的关键。3.3 服务端校验五道关卡拦住异常签到收到请求后不能直接入库要过五道校验。任何一道不过标记为异常待审而不是直接拒绝给申诉留口子。校验项判断逻辑不通过处理令牌有效性Redis 中是否存在且未过期直接拒绝时间窗口服务端时间在签到有效期内标记迟到距离范围距离 ≤ 半径 精度标记异常待审设备唯一同课程同设备只允许一个账号标记异常待审重复签到唯一索引冲突返回已签到// 服务端校验核心逻辑 public SignResult verify(SignRequest req) { // 1. 令牌校验 String cached redisTemplate.opsForValue() .get(sign:token: req.getCourseId()); if (cached null || !cached.equals(req.getToken())) { return SignResult.reject(签到已结束或令牌无效); } // 2. 距离校验把精度算进去 double dist GeoUtil.distance( req.getLatitude(), req.getLongitude(), course.getLatitude(), course.getLongitude() ); boolean inRange dist course.getRadius() req.getAccuracy(); // 3. 设备校验 boolean deviceUsed recordMapper.existsByCourseAndDevice( req.getCourseId(), req.getDeviceId() ); // 任一异常都入库但标记待审不直接拒绝 int status (inRange !deviceUsed) ? 1 : 2; recordMapper.insert(buildRecord(req, status)); return SignResult.ok(status); }注意这里标记待审而不是直接拒绝的设计。定位偶尔飘、设备换新机直接拒绝会误伤真实学生留个待审让老师人工判断体验好很多。4. 避坑与排查那些让签到系统翻车的细节4.1 定位一直返回 null 或精度极差现象学生反馈一直提示定位超时日志里location为 null 或accuracy上百米。原因通常是权限没给全——安卓 6.0 以后定位权限分粗略和精确两级只申请粗略权限拿不到 GPS。解决在 Manifest 里同时声明ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION运行时两个一起请求。另外室内要提示用户开 WiFi纯 GPS 在楼里基本没戏。4.2 同一台手机给多个账号签到现象一个学生拿室友手机挨个签。原因只校验了账号没校验设备。解决device_id用Settings.Secure.ANDROID_ID加应用签名哈希生成同一课程内限制一台设备只能签一个账号。注意别用 IMEI新系统拿不到。4.3 弱网下签到请求丢失现象学生说我点了签到但系统没记录。原因请求发出后网络断了客户端没做重试。解决本地用 Room 建个待提交队列提交失败先落库起个 WorkManager 定时任务在网络恢复后补交补交时带上原始时间戳服务端按时间戳判断是否在有效期内。4.4 服务端时间与客户端时间对不上现象明明在有效期内签到却被判迟到。原因用了客户端时间做判断。解决所有时间判断以服务端为准客户端时间只做展示。签到有效期从服务端发起那一刻算起别信手机时钟。4.5 二维码被拍照外传代签现象老师把二维码投屏有人拍照发给没来的人。解决令牌有效期压到 2 分钟以内并且令牌绑定发起签到的设备或教室 WiFi 的 BSSID扫码时校验 BSSID 是否一致。这招能挡住大部分远程代签。5. 进阶技巧把签到数据用起来和防代签的最后一公里签到系统做完基础功能只是及格真正拉开差距的是数据利用和防代签深度。先说数据。签到记录表积累一学期后能算出每个学生的出勤率、迟到频次、以及总是踩点签到的行为模式。我一般会加一个统计接口按课程和学生两个维度聚合老师一眼能看到谁需要关注。SQL 层面用GROUP BY加条件聚合就够不用上大数据那套。-- 按学生统计出勤情况 SELECT student_id, COUNT(*) AS total, SUM(CASE WHEN status 1 THEN 1 ELSE 0 END) AS normal, SUM(CASE WHEN status 2 THEN 1 ELSE 0 END) AS abnormal, ROUND(SUM(CASE WHEN status 1 THEN 1 ELSE 0 END) / COUNT(*), 3) AS rate FROM sign_record WHERE course_id ? GROUP BY student_id ORDER BY rate ASC;再说防代签的最后一公里。前面讲的令牌、设备、BSSID 能挡住大部分但挡不住人来了手机没来或者手机来了人没来。进阶做法是加一步活体校验签到成功后随机要求拍一张现场照片或者做一次人脸比对。照片方案成本低但要注意隐私合规只存特征不存原图用完即删。人脸比对要接第三方能力小项目不一定值得。还有一个容易被忽略的点签到系统的后悔药机制。学生确实到了但定位飘了得有个申诉入口让他上传一张现场照片或让老师手动补签。这个入口不做客服压力会全压到你身上。我的习惯是异常记录自动进待审列表老师端一键批量处理比让学生挨个找你强得多。最后说个验证方法上线前别只测自己一个人。找三五个同学一个在教室、一个在隔壁楼、一个在操场同时签到看系统判断是否符合预期。再模拟一次断网签到确认补交队列能正常工作。这套流程跑通基本就能交付了。我自己第一次做的时候没测弱网结果正式用的时候一半人签到失败那场面至今记得。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

fpinscala 并行编程:asyncF 组合子解析——从惰性求值到 Par 并行抽象

fpinscala 并行编程:asyncF 组合子解析——从惰性求值到 Par 并行抽象

示例工程 【免费下载链接】fpinscala Code, exercises, answers, and hints to go along with the book "Functional Programming in Scala" 项目地址: https://gitcode.com/gh_mirrors/fp/fpinscala 点击查看 免费下载 在《Functional Programming in S…

2026/10/14 0:00:41 阅读更多 →
冈萨雷斯《数字图像处理》Matlab函数整理:从灰度变换到压缩编码的实战指南

冈萨雷斯《数字图像处理》Matlab函数整理:从灰度变换到压缩编码的实战指南

1. 为什么我要把冈萨雷斯书里的Matlab函数全部整理一遍如果你手头有冈萨雷斯那本《数字图像处理》,大概率经历过这样的场景:书翻到某一章,看到一个处理效果很漂亮的图,想自己动手复现一下,结果发现书里只给了公式和原理…

2026/10/14 0:00:01 阅读更多 →
arm64离线部署Harbor 2.13.1:信创环境私有镜像仓库搭建实战

arm64离线部署Harbor 2.13.1:信创环境私有镜像仓库搭建实战

简介:这是一份面向 ARM 架构服务器环境的 Harbor 容器镜像仓库离线部署包,对应 Harbor 2.13.1 版本,适合在国产化平台、ARM 服务器或内网隔离环境中搭建私有镜像仓库的运维与开发人员使用。压缩包为 tgz 格式,共包含 6 个文件&…

2026/10/13 21:20:23 阅读更多 →

最新新闻

金融时间序列建模全流程:从平稳性检验到GARCH波动率预测

金融时间序列建模全流程:从平稳性检验到GARCH波动率预测

1. 从第一节课到第四章:金融时间序列到底在研究什么如果你正在啃金融相关的课程,大概率会在一门叫《金融时间序列分析》或类似名字的课上卡住。这门课和传统统计学、计量经济学都不一样,它研究的是股票收益率、汇率波动、债券利差这类有“先后…

2026/10/14 0:48:55 阅读更多 →
AgenticOps工程:企业自动化运维的自主决策革命

AgenticOps工程:企业自动化运维的自主决策革命

1. AgenticOps Engineering 的本质与价值AgenticOps Engineering 正在重新定义企业自动化运维的边界。与传统自动化工具不同,这种新型工程范式通过赋予系统自主决策能力,使企业IT基础设施能够像拥有"数字员工"一样主动感知环境变化、预测问题并…

2026/10/14 0:48:55 阅读更多 →
用插件重构知识工作流:浏览器、编辑器与知识库的自动化实践

用插件重构知识工作流:浏览器、编辑器与知识库的自动化实践

知识工作者这个词听起来有点抽象,但落到日常就非常具体:你可能天天在写方案、查资料、写代码、记笔记、做汇报,一天结束回头一看,真正用在"思考"上的时间反而不多,大量时间被复制粘贴、切换窗口、找文件、重…

2026/10/14 0:48:55 阅读更多 →
ABAP单元测试效率提升:ADT工具链实战

ABAP单元测试效率提升:ADT工具链实战

1. 项目概述:当ABAP单元测试遇上效率革命在SAP开发领域,ABAP Unit作为核心测试框架已经存在多年,但真正能将其融入日常开发的团队却不多见。问题不在于框架本身,而在于传统测试流程中存在太多效率断层——从编写测试用例到执行测试…

2026/10/14 0:48:55 阅读更多 →
Python远程批量关机实战:WinRM/WMI/SMB三路径选型与避坑

Python远程批量关机实战:WinRM/WMI/SMB三路径选型与避坑

简介:本资源是一份面向Windows系统管理员与IT运维人员的Python自动化脚本工具包,解决多台设备集中管理场景下的远程批量关机需求,适用于机房巡检、课室终端维护、故障应急处置等实际运维任务。压缩包共3个文件(923B)&a…

2026/10/14 0:48:55 阅读更多 →
尖叫声音样本数据集eva:从包结构到训练基线的完整实践

尖叫声音样本数据集eva:从包结构到训练基线的完整实践

简介:EVA尖叫声音样本数据集是一份面向音乐信息检索(MIR)与音频分类研究的人声尖叫样本库,由台湾清华大学MIR课程项目整理,旨在为尖叫检测、异常声音识别、SVM分类等实验提供稀缺的领域数据。压缩包共63个文件&#xf…

2026/10/14 0:47:55 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →