ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Android HCE门禁卡模拟全解析:从协议原理到APDU实战踩坑

Android HCE门禁卡模拟全解析:从协议原理到APDU实战踩坑 1. 先说结论HCE到底能模拟什么卡不能模拟什么卡去年冬天加班到晚上十一点我站在公司门口翻遍口袋才想起来门禁卡落在工位上物业下班了、同事也走光了最后只能蹲在消防通道等保安巡逻。那种明明门就在眼前却进不去的憋屈让我下定决心把门禁卡塞进手机里。我第一时间想到的就是Android HCEHost-based Card Emulation主机卡模拟。这项技术从Android 4.4开始就内置在系统里可以让手机在没有SE安全芯片的情况下通过App直接响应NFC读卡器的指令——也就是说你的手机可以在读卡器面前伪装成一张卡。不过这里必须先泼一盆冷水HCE确实能模拟卡但它不是万能的。网上教你刷机顶盒模拟Mifare卡的教程十有八九都没说清楚一个核心限制——HCE工作在ISO 14443-4协议层而市面上大量门禁系统用的Mifare Classic走的是ISO 14443-3加上NXP私有加密协议这两套协议根本不兼容。这就好比你用普通话对着一个只会说粤语的保安喊了半天对方完全听不懂。这篇文章主要写给三类人看一是想搞懂HCE原理的Android开发者二是想把自家门禁卡装进手机的折腾党三是做NFC相关产品选型、需要评估HCE方案可行性的工程师。我会把HCE能做什么、不能做什么、怎么判断你手上的门禁卡能不能被模拟、以及实测中会踩的坑一次说清楚。1.1 为什么5分钟就能搞定HCE但你仍要先读懂这张协议表先说为什么5分钟就能搞定。如果你只是想写一个最小可用的HCE App在Android Studio里新建工程、写一个继承HostApduService的类、在Manifest里注册一下、再配置一个AID过滤规则差不多就是这个工作量。不夸张熟练的话五分钟确实够。但写完App和刷开门禁之间隔着一条巨大的鸿沟那就是协议的兼容性。NFC底层协议并不是只有一种一张卡或者一个读卡器可能工作在完全不同的协议栈上。我整理了一张表方便你快速定位协议/卡型ISO 14443-3ISO 14443-4HCE可模拟性常见场景Mifare Classic (M1/S50)支持不支持不可直接模拟多数小区门禁、公司门禁Mifare Ultralight支持不支持不可直接模拟地铁单程票、小面额储值卡Mifare DESFire支持支持通过封装部分可模拟需协议授权交通卡、电子钱包ISO 14443-4 Type A/B CPU卡支持支持可模拟银行卡、部分高端门禁NFC Type 2/3/4 Tag支持视具体Tag而定视协议而定标签贴纸、蓝牙配对注意看第二行和第三行的区别Mifare Classic和Mifare Ultralight工作在ISO 14443-3这一层它们用的是NXP私有的帧格式和加密认证方式而Android的HCE实现直接建立在ISO 14443-4之上卡在物理层就不通。这就像两条独立的地铁线路轨道宽度不一样列车没法在两条线路上互相跑。我见过不少人拿着手机去刷单位门禁读卡器完全没反应就是栽在这个协议差异上。所以第一步优先搞清楚你手上的卡是哪种协议比什么都重要。1.2 HCE能模拟Mifare Classic吗答案一句话不能直接说结论HCE在Android系统上不能直接模拟Mifare Classic卡。这跟破解不破解没关系是物理层和传输层的兼容性问题。Mifare Classic卡常见的就是M1 S50卡的通信过程分为几个阶段读卡器先发送REQA/WUPA请求唤醒卡片然后发送ANTICOLLISION命令获得卡的UID接着执行三轮认证authenticate认证通过后才能读写块数据。这个认证算法叫Crypto1是NXP的私有加密算法它的帧格式是NXP自定义的、基于ISO 14443-3的比特级帧。而HCE的工作方式是读卡器发出SELECT APDU指令系统在已注册的AID里查找匹配项找到后把APDU请求交给对应的App处理App返回APDU响应。整个过程跑在ISO 14443-4的块传输层上完全没有Mifare的那套认证握手接口。有人会问那我把Crypto1的算法用软件实现在HCE里不就行了吗问题在于你的代码根本接触不到那一层帧数据——Android系统没有向上层App暴露ISO 14443-3的比特级帧接口。App能拿到的已经是ISO 14443-4块内的APDU内容而Mifare Classic的整个通信流程根本就不走APDU。所以如果在网上看到有人说用HCE模拟Mifare Classic成功刷开小区门禁要么是门禁读卡器其实支持ISO 14443-4的CPU卡要么就是他用了别的硬件方案比如外接PN532而不是纯Android HCE。别被标题党带偏了。1.3 HCE与门禁读卡器之间的对话到底长什么样理解HCE的通信方式用一句人话概括就是读卡器是老板你的App是员工两者之间靠一张张任务纸条APDU指令来沟通。一张APDU请求大概长这样00 A4 04 00 07 A0 00 00 00 03 00 00 00翻译成人话就是老板递过来一张纸条上面写着我要选择AID编号为A0000000030000的这个应用请你做好准备。你的App收到这张纸条后需要回复一句收到我准备好了也就是返回一个状态码90 00。再看一个实际门禁系统可能的交互流程读卡器 -: 00 A4 04 00 07 A0 00 00 00 03 00 00 00 (选择应用) App -: 90 00 (应用选择成功) 读卡器 -: 00 B0 01 00 00 (读取数据块) App -: 61 10 01 02 03 ... 90 00 (返回16字节数据)这整套机制看起来不复杂但难点在于你并不知道对方门禁系统具体会发出什么指令。每个门禁厂商的协议都不太一样有的厂商用的是通用的读卡指令有的则是私有协议。这也是为什么HCE做Demo容易、做真实对接难的根本原因。所以5分钟搞定NFC门禁卡模拟这个标题其实可以拆成两层5分钟搞定的是HCE模拟卡的骨架真正费时间的是让骨架匹配你那个门禁系统的具体协议。2. Android工程里最容易被忽略的4个关键配置HCE项目本身不复杂但配置步骤里有几个细节一旦搞错问题会非常难排查。我在第一次跑通HCE的时候就因为在Manifest里少写了一个属性导致整个Service压根不会被系统识别手机贴上去读卡器毫无反应而且Logcat里还没有任何提示。这节我把关键配置拆开讲照抄即可。2.1 Manifest清单Service注册与BIND_NFC_SERVICE缺一不可HostApduService本质是一个Service但它跟普通Service的注册方式有点不一样。直接在application标签里加这样一段service android:name.service.CardEmulationService android:exportedtrue android:permissionandroid.permission.BIND_NFC_SERVICE intent-filter action android:nameandroid.nfc.cardemulation.action.HOST_APDU_SERVICE / /intent-filter meta-data android:nameandroid.nfc.cardemulation.host_apdu_service android:resourcexml/apduservice / /service这里有两个关键点第一android:permissionandroid.permission.BIND_NFC_SERVICE不能省。这个权限的作用是只有系统NFC服务才能绑定到你这个Service上。如果漏了系统在路由APDU的时候找不到合法的Service手机靠近读卡器就完全没有反应。第二android:exportedtrue必须显式声明。从Android 12开始系统要求显式指定exported否则编译阶段就直接报错。还有一个容易被忽略的点xml/apduservice这个XML文件要放在res/xml/目录下如果你建项目时没有这个目录记得手动创建。文件内容下面会详细讲。2.2 AID配置让读卡器敲门时系统能找到你apduservice.xml是HCE的灵魂文件它告诉系统你的App负责处理哪些AID对应的卡片模拟。AID全称Application ID是NFC读卡器选择应用时用的唯一标识由ISO/IEC 7816-5规范定义。读卡器发送SELECT APDU指令后系统会根据指令里的AID到所有已注册的Service里查找匹配项。一个最基础的apduservice.xml长这样host-apdu-service xmlns:androidhttp://schemas.android.com/apk/res/android android:descriptionstring/app_name android:requireDeviceUnlockfalse aid-group android:descriptionstring/app_name android:categoryother aid-filter android:nameF222222222 / !-- 这里是测试用AID实际项目中替换为你需要响应设备的标准AID -- /aid-group /host-apdu-serviceAID的格式要求是十六进制字符串偶数位长度最少2位最多32位。常见的有两类路径AID例如F222222222以F开头一般用于私有应用自定义比较自由。完整AID例如A000000151000000前缀由ISO分配通常对应某个标准应用如GP规范。这里有一个很常见的误解AID不是你想怎么定就怎么定读卡器端的SELECT指令必须带上同样AID你的Service才会被路由到。所以如果你是对接真实门禁系统AID必须跟门禁读卡器配发的一致这个信息通常需要向门禁厂商或系统集成商索取不是猜出来的。2.3 前台调度Foreground Dispatch抢回NFC事件处理权当你写完HCE Service把手机贴近门禁读卡器时系统默认的逻辑是先看前台有没有App在等NFC事件再看有没有匹配的HCE Service。如果在测试过程中手机弹出打开NFC标签阅读器之类的系统页面或者被手机自带的NFC工具App拦截了那你需要启用前台调度来抢占NFC事件。前台调度的核心代码写在Activity里private fun enableNfcForegroundDispatch() { val nfcAdapter NfcAdapter.getDefaultAdapter(this) ?: return val pendingIntent PendingIntent.getActivity( this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) val filters arrayOf( IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED), IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED) ) val techLists arrayOf( arrayOf(IsoDep::class.java.name), arrayOf(NfcA::class.java.name), arrayOf(MifareClassic::class.java.name) ) nfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, techLists) }在onResume()里调用enableNfcForegroundDispatch在onPause()里调用disableForegroundDispatch否则会导致泄漏或者事件处理混乱。实际测试中我发现同一个App里同时注册HCE Service和前台调度时普通读卡器并不会触发前台调度的回调而是会走HCE的Service逻辑。前台调度主要影响的是NFC标签发现这一类事件。如果你测试时手机弹出的不是你预期的弹窗先检查一下是否有其他App比如各种NFC读取工具也注册了相同或类似的NFC过滤规则在设置-连接设备-NFC-默认钱包/默认应用里把默认NFC应用切换成你的App。2.4 最容易踩坑Android 12的NFC默认应用选区变化这个问题网上搜不到多少中文资料但我在Android 14的真机上踩得很疼从Android 10开始系统对NFC默认应用的逻辑做了调整用户在设置-NFC-默认应用里选择某个App后该App会成为NFC读卡器的首选路由目标。如果你在测试时发现手机贴上去系统总是弹出是否打开某某应用而你的Service明明配置没问题那就去检查一下默认应用是不是被系统重置了。另外android:requireDeviceUnlock这个属性我也踩过一回。它的含义是当设备锁屏时是否允许HCE Service被唤起。如果设成true锁屏状态下手机贴近读卡器系统不会唤醒你的Service门禁当然刷不开。某些门禁系统要求锁屏也能刷这时候记得把这个属性设成falsehost-apdu-service android:descriptionstring/app_name android:requireDeviceUnlockfalse3. APDU服务实现你写的是应答逻辑不是卡配置搞定后接下来就是核心代码。我先给出一份最小可用的实现然后再解释里面的门道。3.1 一个最小可用的HostApduService实现用Kotlin写的话大概长这样package com.example.hcecard import android.nfc.cardemulation.HostApduService import android.os.Bundle import android.util.Log class CardEmulationService : HostApduService() { companion object { private const val TAG CardEmulation // 测试用AID正式环境请替换为你需要处理的标准AID val SELECTABLE_AIDS listOf(F222222222) } override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray { Log.d(TAG, 收到APDU指令: ${commandApdu.toHexString()}) // 判断是否 SELECT 指令 val isSelect commandApdu.size 5 commandApdu[0] 0x00.toByte() commandApdu[1] 0xA4.toByte() return if (isSelect) { // 应用选择成功后返回成功状态 byteArrayOf(0x90.toByte(), 0x00.toByte()) } else { // 其他指令先统一返回不支持 byteArrayOf(0x6A.toByte(), 0x82.toByte()) } } override fun onDeactivated(reason: Int) { Log.d(TAG, 卡片模拟被取消原因: $reason) } private fun ByteArray.toHexString(): String joinToString(separator ) { byte - %02X.format(byte) } }这段代码做了什么简单来说当读卡器发出SELECT指令选择你的AID时你的服务回复一个选择成功90 00当读卡器发出其他指令时你的服务回复文件未找到6A 82。这么简单的代码当然刷不开真实门禁它的意义在于让你确认系统路由通了、Service活了、APDU能走起来了。先跑通这个最小环再往里面填业务逻辑这是HCE开发的正确顺序。3.2 读懂APDU请求与返回码9000不是唯一答案APDU指令分为两部分头部Header和正文Body。头部通常是4个字节CLA INS P1 P2每个字节的含义分别是CLA指令类别常用00表示ISO 7816标准指令。INS指令类型比如A4表示SELECT选择、B0表示READ BINARY读取二进制、D0表示WRITE BINARY写入、C0表示GET RESPONSE获取响应。P1/P2参数具体含义取决于指令类型。后面的字节是Lc正文长度、正文数据、Le期望返回长度。比如00 A4 04 00 07 A0 00 00 00 03 00 00 00拆开来看字段值含义CLA00标准指令INSA4SELECT选择P104按AID名称选择P200第一个或唯一一个匹配项Lc07后面跟着7个字节的AIDDataA0 00 00 00 03 00 00要选择的AID返回的状态码SW1 SW2则需要记住几个最常用的值状态码含义90 00成功6A 82文件/应用未找到6A 86参数P1/P2错误6D 00指令不支持INS错误6E 00类别不支持CLA错误63 00认证失败69 85使用条件不满足调试HCE服务时最直观的方式就是在Logcat里打印收到的commandApdu然后对照这张表去判断自己返回的状态码合不合理。我自己的经验是先把所有未知指令统一返回6A 82然后逐个根据日志增加响应逻辑。这比一开始就试图实现完整协议要高效得多。3.3 针对只读UID型的门禁系统HCE为什么无能为力很多小区门禁的验证逻辑特别简单读卡器只读取卡片的UID唯一标识符然后跟后台数据库比对。这种系统用Mifare Classic卡居多但也不是绝对有些CPU卡门禁系统也可能只读UID。问题在于HCE模式下Android系统没有向App暴露设置或获取UID的接口。在HCE的通信模型里卡片模拟方的UID由NFC控制器硬件决定而且通常每次会话还会随机变化部分设备是这样App根本控制不了这一个值。如果你拿HCE去模拟一张Mifare Classic卡的门禁读卡器那边在ANTICOLLISION阶段就失败了——因为你的手机模拟出来的UID跟门禁系统里登记的那张卡的UID对不上。这也是为什么很多把门禁卡模拟到手机里的方案实际上用的是手机系统自带钱包的NFC模拟功能或者额外硬件比如ACR122U、PN532因为它们可以做到在更底层去模拟整张卡或者固定UID。所以当你确认门禁系统是只读UID型而你又坚持要用HCE那基本就是死路一条。正确的做法是换方案而不是在HCE这条路上死磕。4. 实测判断手上的门禁卡能不能被HCE模拟这里我要教你一个在动手前就能完成的三步判断法。很多人一上来就写代码写到一半才发现协议不兼容白白浪费半天。先花十分钟判断一下比你写两百行代码都有用。4.1 用手机查卡类型两分钟判断Mifare Classic还是ISO14443-4首先你需要一台带NFC的Android手机然后在应用商店搜索NFC Tag Info或者类似的NFC读卡工具。这类工具的基本逻辑是手机靠近卡片后会读取Tag的协议信息和内容。操作步骤如下打开NFC Tag Info应用把门禁卡紧贴手机背面通常在摄像头附近的主线圈区域。应用会弹出卡片类型和技术列表主要看两项NFC-AISO 14443-3ISO 14443-4 / ISO-DEP如果列表里出现了MifareClassic或者NXP MIFARE Classic那这张卡就是Mifare Classic。如果列表里出现了IsoDep或者ISO-DEP说明这张卡走的是ISO 14443-4HCE有机会可模拟。这里有个小技巧如果手机贴近卡片时NFC Tag Info根本读不到卡只有已检测到NFC标签的提示但无法解析标签类型那大概率是一张非标准的私有卡或者加密卡HCE方案基本可以放弃。我自己拿了一张食堂卡和一张公司门禁卡试过结果很典型食堂卡显示的是MifareClassic公司门禁卡显示的是IsoDep。所以结论很明确公司门禁可以尝试HCE食堂卡没戏。4.2 通过读卡器型号判断门禁系统类型如果你手边正好能看到门禁读卡器就是墙上那个刷卡的设备可以看一眼型号和品牌然后做初步判断。常见的几类读卡器如下读卡器形态常见品牌/型号倾向协议是否适合HCE老式蓝色/黑色长方形读卡器中控、ZKTeco多为Mifare Classic不适合支持CPU卡的高端读卡器HID iCLASS SE、Desfire读卡器ISO 14443-4适合带键盘的密码刷卡一体机海康、大华门禁一体机不确定需查型号视具体型号圆柱形读卡器常用于宿舍门常见杂牌多为Mifare Classic不适合这个方法不是100%准确因为很多读卡器同时支持多种协议比如某些高档读卡器能同时读Mifare和ISO 14443-4的卡。但它能帮你筛掉最典型的情况如果读卡器上印着MIFARE字样那基本就没戏了。这里要特别提醒不要因为读卡器长得老就觉得它一定不支持CPU卡。我见过一个小区用的读卡器外观特别复古但拆开看参数表才发现它同时支持ISO 14443-4。所以型号判断只能作为辅助最终以卡片的协议检测结果为准。4.3 可行的替代方案当HCE走不通时的三条路如果你的卡是Mifare ClassicHCE这条路走不通那还有几个方向可以尝试。这里我只讨论你有合法权限的场景比如这是你自己的门禁卡或者你获得了小区物业的授权。方案一使用NFC读写模块刷写UID卡。买一张可写UID的空白卡比如UID卡、CUID卡、FUID卡用PN532或者ACR122U把原卡数据复制到新卡上。这个方案的缺点是需要在手机上装额外的读写App优点是成本低、成功率极高Mifare Classic的扇区数据都能完整复制前提是你的门禁卡没有启用特殊的防复制机制比如滚动码或者UID白名单。方案二更换门禁系统方案。如果你能联系到物业或者公司行政沟通是否能升级门禁读卡器让它支持ISO 14443-4的CPU卡。这个方案的成本最高但也是唯一能够从底层解决HCE模拟门禁卡问题的正路。方案三使用支持HCE的第三方门禁平台。近年来有些智能门禁平台比如某些支持蓝牙NFC手机开门的系统已经内置了HCE支持你只需要在App里绑定门禁卡手机就能直接刷。这个方案虽然不是你自己写HCE代码但原理是一样的而且由厂商做好了协议适配。我个人试验下来宿舍楼的Mifare门禁卡最省事的方案是换一张CUID卡因为大部分宿舍门禁只校验UID不校验数据写个空UID卡就能刷。而公司门禁卡则因为走的是CPU卡协议HCE方案反而有戏。你手头的卡属于哪种先按4.1的方法查一遍再说。5. 从完全不行到成功刷卡我的排查记录这一节我把实际操作中踩过的坑按症状-排查-解决的方式记录下来。如果你是照着前面代码写得差不多了但刷不开门大概率能在下面找到对应的问题。5.1 问题一手机刷上去门禁毫无反应这个现象最让人崩溃手机贴上去读卡器什么动静都没有Logcat里连一条APDU日志都没打出来。排查思路按照优先级排列检查Manifest的Service配置BIND_NFC_SERVICE权限有没有漏exported有没有设成trueaction名是不是android.nfc.cardemulation.action.HOST_APDU_SERVICE。漏任何一个系统都不会路由。检查AID是否匹配模拟卡时读卡器发出了SELECT指令但你的Service里注册的AID不在读卡器的选择列表里系统一样不会路由。检查系统NFC设置里的默认应用在设置-连接设备-NFC-默认应用里把你的App设为默认NFC应用避免被其他App抢占。检查手机支持度部分旧机型或某些定制ROM对HCE支持不完善需要在系统设置里打开卡模拟开关一般在NFC设置页面里不同品牌叫法不一样。我自己的排查顺序是先重新读一遍Manifest确认没问题后再用adb shell cmd nfc命令查看NFC服务状态。这里有个实用命令adb shell dumpsys nfc | grep -A 20 mCardEmulationManager输出里能看到系统注册的AID列表和当前路由状态如果里面没有你的F222222222说明系统压根没把你的Service注册进去问题一定出在前面三步。5.2 问题二服务能收到APDU但总是返回失败这种情况意味着系统路由已经到了你的Service但APDU交互没有走通。常见现象是读卡器亮了一下红灯或者发出滴滴的报错声。我的做法是先在Logcat里打全日志观察具体是哪一条APDU导致失败。比如我碰到过的一个场景读卡器发来00 A4 04 00 07 A0 00 00 00 03 00 00 00我的代码返回了90 00然后读卡器又发来00 B0 01 00 00我原样返回6A 82然后门禁就报错了。这就说明读卡器在SELECT之后还有一个读取卡内数据的步骤你的Service必须对这个指令返回正确的数据而不能一概返回不支持。至于应该返回什么数据这就要看门禁系统的协议文档了。如果你是跟门禁厂商合作的向对方索要APDU协议文档如果是自己逆向测试的就得靠抓包和尝试了。这里有一个调试技巧用一个支持监听NFC通信的读卡器比如ACR122U配合PC端的NFC读取软件去唤起你的HCE服务然后抓取读卡器发出的所有APDU指令这样比在手机上盲猜要高效得多。5.3 问题三一次成功一次失败刷十次有三四次失败这种时灵时不灵的问题最让人抓狂。我遇到过的情况是手机贴近读卡器后有时候能刷开有时候没反应间隔时间还不固定。排查之后发现原因有三类第一类是NFC天线位置问题。手机背面真正的NFC线圈区域并不是整个后盖而是一个小的矩形区域通常在摄像头附近。很多人在刷手机时习惯性用手机全身去贴读卡器结果NFC线圈没有对准读卡器的感应区导致信号不稳定。解决办法是多试几个角度和位置找到自己手机的最佳刷卡点。第二类是NFC天线兼容性问题。部分读卡器对手机NFC天线的灵敏度要求较高哪怕位置对上了偶尔也会握手失败。这属于硬件兼容性问题无解但可以通过调整刷卡位置缓解。第三类是系统路由优先级不稳定。Android系统在路由NFC事件时如果同时有多个App注册了NFC服务可能会出现优先级竞争。把其他无关的NFC应用卸载掉或者禁用能明显降低失败率。5.4 排查HCE小技巧汇总再总结几个实用技巧都是我实际用过的用Logcat打印所有APDU收发这是最高效的调试方式每次刷卡都能看到完整的指令流。用NFC读卡器工具模拟读卡器端PC端的读卡工具比手机调试方便得多能精确控制指令内容。在apduservice.xml里多配置几个AID如果你不确定读卡器会使用哪个AID可以同时配置多个系统会逐个尝试。留意系统NFC服务有没有自动重启开发过程中如果改过Manifest或者AID相关代码最好杀掉App进程重新安装再测试避免旧配置残留。还有一个我自己当时没注意到的细节HCE的onDeactivated回调一定要打印日志。每次刷卡结束后系统都会回调这个方法原因值代表不同的取消原因DEACTIVATION_LINK_LOSS表示读卡器移开DEACTIVATION_DESELECTED表示读卡器主动取消选择DEACTIVATION_TIMEOUT表示超时。如果你发现刷一次门禁会连续收到多次onDeactivated回调说明读卡器那边其实已经完成了好几轮APDU交互只是你的日志没打全。6. 最后的经验与可扩展方向说点实在的。HCE做门禁模拟这件事技术本身不算难难在对边界的理解。我在做这个项目的过程中最大的收获是搞清楚能不能做比怎么做重要得多。协议不兼容代码写得再漂亮也白搭。如果你手头的门禁卡确认是ISO 14443-4协议的CPU卡那恭喜你HCE方案有很大概率能跑通。我建议你从最简单的SELECTREAD应答逻辑开始先用最小Demo验证路由再逐步扩展指令响应。如果你手头的卡是Mifare Classic也别灰心换用UID卡复制的方案反而能更快达成目标。最后分享一个扩展方向HCE还能用来做很多有趣的事不只是门禁。比如你可以用HCE实现一个简单的数字名片——手机贴近别人的NFC读卡器时自动传递你的联系方式或者做一个NFC签到系统——手机靠近签到机自动完成打卡。这些应用场景的本质都是一样的让Android设备在ISO 14443-4协议下扮演一张CPU卡的角色。我最近就在尝试把一个简单的NFC电子票Demo跑通用HCE模拟一张包含票务信息的卡片让检票机可以读取。相比门禁系统这类场景的协议往往更标准化HCE的落地成功率也更高。如果你对HCE有兴趣完全可以顺着这个方向继续深入。
返回列表