尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

NFC签到三步实现核心流程

NFC签到三步实现核心流程 NFC签到打卡核心实现三步走基于NFC技术实现签到打卡功能其核心在于利用NFC标签的便捷性与唯一性将物理触碰转化为数字化的考勤记录。整个过程可概括为三个关键步骤1. 数据写入与初始化、2. 前台调度与标签读取、3. 数据处理与持久化。以下将结合具体技术细节与代码示例详细解析每一步的实现。第一步数据写入与标签初始化此步骤是系统运行的基础负责将代表用户或设备身份的唯一信息如员工ID、学号、设备编码等写入NFC标签。数据格式遵循NDEF标准以确保广泛的兼容性。1. 核心概念与数据格式NDEF消息由一条或多条NDEF记录组成每条记录包含报头、类型长度、载荷长度和实际数据。对于签到应用最常用的是TEXT或URI类型的记录。TEXT记录可直接存储可读文本而URI记录则适合存储一个用于触发应用或访问后台服务的URL。2. 代码实现向标签写入NDEF数据// 核心代码将文本数据写入NFC标签 import android.nfc.NdefMessage import android.nfc.NdefRecord import android.nfc.tech.Ndef import android.nfc.Tag import java.nio.charset.StandardCharsets fun writeTextToTag(tag: Tag?, textToWrite: String): Boolean { tag?.let { val ndef Ndef.get(it) ndef?.let { nfcTag - try { nfcTag.connect() // 1. 创建文本NDEF记录 val languageCode en // 语言编码 val textBytes textToWrite.toByteArray(StandardCharsets.UTF_8) val payload ByteArray(1 languageCode.length textBytes.size) payload[0] languageCode.length.toByte() System.arraycopy(languageCode.toByteArray(), 0, payload, 1, languageCode.length) System.arraycopy(textBytes, 0, payload, 1 languageCode.length, textBytes.size) val textRecord NdefRecord.createTextRecord(languageCode, textToWrite) // 2. 创建NDEF消息可包含多条记录 val message NdefMessage(arrayOf(textRecord)) // 3. 写入标签 if (nfcTag.isWritable) { nfcTag.writeNdefMessage(message) return true // 写入成功 } else { Log.e(NFC_WRITE, Tag is not writable.) } } catch (e: Exception) { Log.e(NFC_WRITE, Write operation failed, e) } finally { try { nfcTag.close() } catch (e: IOException) { // 忽略关闭异常 } } } } return false // 写入失败 }代码说明Ndef.get(tag)获取标签的NDEF技术接口对象。createTextRecord便捷方法创建标准文本NDEF记录内部实现了上述payload的构建逻辑。writeNdefMessage将封装好的NDEF消息写入标签这是数据持久化的关键操作。异常处理是必须的因为标签可能在写入过程中被移开导致通信中断。3. 应用场景与初始化策略在实际部署中标签初始化通常在后台管理端完成。例如为每位员工分配一个唯一的NFC工卡。写入的数据可以是简单的员工编号如EMP1001也可以是一个包含加密令牌和用户信息的JSON字符串。对于高安全场景可以考虑使用NDEF记录中的URI类型指向一个需要认证才能访问的签到API端点实现动态验证 。第二步前台调度与标签读取监听当初始化好的标签被员工持有时签到应用需要在设备如手机或平板端可靠地侦测并读取标签内容。Android系统通过NfcAdapter和PendingIntent机制实现前台调度。1. 配置与权限声明首先在AndroidManifest.xml中声明NFC权限并设置Intent过滤器以声明应用对NFC事件感兴趣。uses-permission android:nameandroid.permission.NFC / uses-feature android:nameandroid.hardware.nfc android:requiredtrue / activity android:name.SignInActivity intent-filter !-- 当扫描到包含文本NDEF记录的标签时启动此Activity -- action android:nameandroid.nfc.action.NDEF_DISCOVERED / category android:nameandroid.intent.category.DEFAULT / data android:mimeTypetext/plain / /intent-filter !-- 兼容处理如果标签不是标准NDEF格式但能被识别为NFC标签则通过此过滤器 -- intent-filter action android:nameandroid.nfc.action.TAG_DISCOVERED / category android:nameandroid.intent.category.DEFAULT / /intent-filter /activity配置说明NDEF_DISCOVERED过滤器提供了更精确的控制只有当标签包含匹配mimeType的数据时才唤醒应用这可以减少不必要的应用唤醒提升用户体验和系统效率。2. 启用前台调度与读取数据在负责签到的Activity如SignInActivity中需要在onResume生命周期中启用前台调度并在onPause中禁用以节省资源。// 核心代码在Activity中启用前台调度并处理NFC Intent import android.app.PendingIntent import android.content.Intent import android.content.IntentFilter import android.nfc.NdefMessage import android.nfc.NfcAdapter class SignInActivity : AppCompatActivity() { private lateinit var nfcAdapter: NfcAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) nfcAdapter NfcAdapter.getDefaultAdapter(this) } override fun onResume() { super.onResume() // 1. 创建一个PendingIntent当发现NFC标签时系统会将其发送到当前Activity val pendingIntent PendingIntent.getActivity( this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0 ) // 2. 创建Intent过滤器数组指定要处理的NFC标签类型 val ndefFilter IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { try { addDataType(text/plain) // 匹配文本类型 } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException(MIME type error, e) } } val tagFilter IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED) val filters arrayOf(ndefFilter, tagFilter) // 3. 指定要处理的技术列表可选用于更精细的控制 val techLists arrayOf(arrayOf(android.nfc.tech.Ndef::class.java.name)) // 4. 启用前台调度 nfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, techLists) // 处理从NFC Intent传递过来的数据例如应用从后台被NFC事件启动时 processIntent(intent) } override fun onPause() { super.onPause() // 5. 在Activity失去焦点时禁用前台调度 nfcAdapter.disableForegroundDispatch(this) } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) // 当Activity已在栈顶并被NFC事件再次触发时会调用此方法 processIntent(intent) } private fun processIntent(intent: Intent) { if (NfcAdapter.ACTION_NDEF_DISCOVERED intent.action) { val rawMessages intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES) rawMessages?.firstOrNull()?.let { msg - val ndefMessage msg as NdefMessage // 提取第一条NDEF记录中的文本数据 val payload ndefMessage.records[0].payload val textEncoding if ((payload[0].toInt() and 128) 0) UTF-8 else UTF-16 val languageCodeLength payload[0].toInt() and 0x3F val text String( payload, languageCodeLength 1, payload.size - languageCodeLength - 1, Charset.forName(textEncoding) ) Log.d(NFC_READ, Read from tag: $text) // 触发签到逻辑如显示员工姓名准备上传数据 handleSignIn(text) } } } private fun handleSignIn(userIdentifier: String) { // 这里实现具体的签到逻辑如验证用户、记录时间等 Toast.makeText(this, 签到成功: $userIdentifier, Toast.LENGTH_SHORT).show() // 可以进一步调用方法将数据保存到本地或上传到服务器 } }代码逻辑解析enableForegroundDispatch这是核心方法它允许当前Activity优先于系统内其他可能响应NFC事件的应用接收标签。PendingIntent定义了当NFC事件发生时系统应如何启动或通知当前Activity。processIntent负责解析从Intent中提取的NDEF消息还原出最初写入标签的文本信息如员工ID。安全考量此模式为前台调度仅在应用界面可见时有效避免了后台恶意读取但读取到的数据仍需在服务器端进行真实性验证以防止标签被复制或篡改 。第三步数据处理、存储与同步读取到标签数据用户身份标识后系统需要完成签到记录的处理包括时间戳记录、本地存储和网络同步确保数据的完整性和可靠性。1. 数据模型与本地存储使用Android Jetpack的Room持久化库可以方便地在本地SQLite数据库中存储签到记录。// 1. 定义数据实体 (Entity) import androidx.room.Entity import androidx.room.PrimaryKey import java.util.Date Entity(tableName check_in_records) data class CheckInRecord( PrimaryKey(autoGenerate true) val id: Long 0, val userId: String, // 从NFC标签读取的用户标识 val checkInTime: Date, // 签到时间戳 val location: String? null, // 可选签到地点可通过GPS获取 val isSynced: Boolean false // 标记是否已同步到服务器 ) // 2. 定义数据访问对象 (DAO) import androidx.room.Dao import androidx.room.Insert import androidx.room.Query import androidx.room.Update Dao interface CheckInRecordDao { Insert suspend fun insert(record: CheckInRecord): Long Query(SELECT * FROM check_in_records WHERE isSynced 0) suspend fun getUnsyncedRecords(): ListCheckInRecord Update suspend fun update(record: CheckInRecord) } // 在handleSignIn方法中调用 private suspend fun saveRecordToLocal(userId: String) { val record CheckInRecord( userId userId, checkInTime Date(), // 使用当前时间作为签到时间 location getLastKnownLocation() // 伪代码获取位置 ) val recordId checkInRecordDao.insert(record) Log.d(DATA, Record saved locally with ID: $recordId) }架构优势本地数据库提供了离线工作能力。在网络不佳或断网时如地下车库、偏远教室签到记录可先安全地保存在设备本地待网络恢复后再同步这是工业级考勤系统必备的健壮性设计。2. 网络同步与安全传输将本地存储的未同步记录通过加密通道上传至服务器。这里使用Retrofit进行网络请求。// 1. 定义API接口和数据传输对象 (DTO) import retrofit2.http.Body import retrofit2.http.POST data class CheckInRequest(val userId: String, val timestamp: Long, val location: String?) data class CheckInResponse(val success: Boolean, val recordId: String) interface CheckInApiService { POST(api/checkin) suspend fun uploadCheckIn(Body request: CheckInRequest): CheckInResponse } // 2. 实现同步逻辑 class SyncRepository(private val apiService: CheckInApiService, private val dao: CheckInRecordDao) { suspend fun syncUnsyncedRecords() { val unsynced dao.getUnsyncedRecords() for (record in unsynced) { try { val request CheckInRequest( userId record.userId, timestamp record.checkInTime.time, location record.location ) val response apiService.uploadCheckIn(request) if (response.success) { // 标记为已同步 dao.update(record.copy(isSynced true)) Log.i(SYNC, Record ${record.id} synced successfully.) } } catch (e: Exception) { Log.e(SYNC, Failed to sync record ${record.id}, e) // 可根据错误类型如网络超时、服务器错误决定重试策略 } } } }安全与优化数据加密建议在CheckInRequest传输前对关键字段如userId进行AES等对称加密或在HTTPS基础上使用应用层签名防止中间人攻击和数据篡改。同步策略同步操作应在后台服务如WorkManager中执行并选择合适的网络条件如仅Wi-Fi和重试机制以平衡用户体验与数据可靠性。数据去重服务器端应基于userId和timestamp等字段实现防重放机制防止同一打卡记录被重复提交。总结三步流程对比与扩展应用下表总结了NFC签到打卡三个核心步骤的职责、关键技术及优化方向步骤核心职责关键技术/组件典型挑战与解决方案1. 数据写入与初始化将身份标识固化到物理标签NDEF格式、Ndef类、标签读写器标签兼容性使用标准NDEF格式确保最大兼容性。安全性可写入加密令牌或一次性码由服务器验证 。2. 前台调度与读取在App前台可靠捕获并解析标签数据NfcAdapter、PendingIntent、IntentFilter、前台调度用户体验快速响应提供声音/震动反馈。后台处理通过enableReaderMode可实现更高效、低功耗的后台读取需权衡功耗与需求。3. 数据处理与同步记录、存储并上传签到数据保证不丢失Room数据库、Retrofit网络库、WorkManager离线能力本地数据库是核心。数据安全网络传输加密与服务器端验签。同步冲突采用“本地优先冲突上报”策略 。此“三步走”框架构成了NFC签到系统的基础。在此基础上可根据具体场景进行扩展例如复杂班制与异常识别在第三步的handleSignIn逻辑中集成AI算法根据打卡时间、地点与预设班次规则进行匹配自动识别迟到、早退、异地打卡等异常情况 。与物联网设备联动在教室管理系统中NFC打卡成功后可自动触发打开投影仪、空调等设备实现智能化场景联动 。纯云端轻量化部署采用SaaS架构客户端App仅负责读取NFC标签ID并上传所有复杂的班制匹配、权限管理和报表生成均在云端完成极大降低本地部署和维护成本 。参考来源Android NFC开发实战入门项目Demo功能完整的安卓NFC开发实战项目——实现手机平板打卡签到系统学习黑客NFC技术详解详解RFID技术在人员签到系统中的应用基于NFC的多媒体教室管理系统设计与实现完整项目校园签到场景下的考勤技术痛点与轻量化解决方案——基于栎偲考勤神器的实测解析
返回列表