NFC在我们生活中出现的场景越来越多了,如蓝牙耳机的连接、刷交通卡、智能锁开锁等,相信在未来还会有越来越多的场景会用到NFC,所以作为开发者,掌握NFC的知识及NFC的开发技能、就显得尤为必要

这里放出Android官方文档,官方的文档讲的大而全,本文是对官方文档的抽丝剥茧,相对官方文档来说会更容易理解,但是会比官方文档少一些内容,如果本文没有你想了解的,可以自己查阅官方文档。

什么是NFC

NFC是Near Field Communication缩写,即近距离无线通讯技术。由飞利浦公司和索尼公司共同开发的NFC是一种非接触式识别和互联技术,可以在移动设备、消费类电子产品、PC 和智能控件工具间进行近距离无线通信。

简单的说,NFC提供了一种简单、触控式的解决方案,可以让消费者简单直观地交换信息、访问内容与服务。

NFC的工作模式

NFC的工作模式有三种,分别是读卡器模式(Reader/writer mode)、仿真卡模式(Card Emulation Mode)、点对点模式(P2P mode)。

  • 读卡器模式

    数据在NFC芯片中,可以简单理解成“刷标签”。本质上就是通过支持NFC的手机或其它电子设备从带有NFC芯片的标签、贴纸、名片等媒介中读写信息。通常NFC标签是不需要外部供电的。当支持NFC的外设向NFC读写数据时,它会发送某种磁场,而这个磁场会自动的向NFC标签供电。

  • 仿真卡模式

    数据在支持NFC的手机或其它电子设备中,可以简单理解成“刷手机”。本质上就是将支持NFC的手机或其它电子设备当成借记卡、公交卡、门禁卡等IC卡使用。基本原理是将相应IC卡中的信息凭证封装成数据包存储在支持NFC的外设中 。

    在使用时还需要一个NFC射频器(相当于刷卡器)。将手机靠近NFC射频器,手机就会接收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的电脑,并进行相应的处理(如电子转帐、开门等操作)。

  • 点对点模式

    该模式与蓝牙、红外差不多,用于不同NFC设备之间进行数据交换,不过这个模式已经没有有“刷”的感觉了。其有效距离一般不能超过4厘米,但传输建立速度要比红外和蓝牙技术快很多,传输速度比红外块得多,如过双方都使用Android4.2,NFC会直接利用蓝牙传输。这种技术被称为Android Beam。所以使用Android Beam传输数据的两部设备不再限于4厘米之内。

    点对点模式的典型应用是两部支持NFC的手机或平板电脑实现数据的点对点传输,例如,交换图片或同步设备联系人。因此,通过NFC,多个设备如数字相机,计算机,手机之间,都可以快速连接,并交换资料或者服务。

本文会主要讲解**读卡器模式,**相信理解了这个模式,其他的两种模式你也会触类旁通的。在讲解读卡器模式前,有一些知识是需要提前掌握的。

卡片的知识

  本文主要讲解的是NFC的读卡器模式,要想读到卡片的内容,我们要对卡片有一些基本的了解,比如卡片的分类,每种卡片内部的数据结构等。

卡片的分类

  现在市面上的卡片分类有IC卡、ID卡、M1卡和CPU卡,简单的了解一下这些卡的区别和用途,

  • IC卡

    IC卡又称集成电路卡,通常是在塑料卡片内嵌入一个或多个集成电路构成的PVC卡。集成电路芯片可以是存储器或微处理器。带有存储器的IC卡又称为记忆卡或存储卡,带有微处理器的IC卡又称为智能卡或智慧卡。记忆卡可以存储大量信息;智能卡则不仅具有记忆能力,而且还具有处理信息的功能。

    IC卡可以十分方便地存汽车费、电话费、地铁乘车费、食堂就餐费、公路付费以及购物旅游、贸易服务等。

  • ID卡

    ID卡又叫身份识别卡,是一种不可写入的感应式卡,拥有一个固定卡号编号。卡号在封卡前写入后不可再更改,绝对确保卡号的唯一性和安全性。

    ID卡可以作为一般的门禁或停车场系统的使用者身份识别,因ID卡无密钥安全认证机制,且不能写卡,很难实现一卡通功能,同时也不合适做消费系统。

  • M1卡

    M1是菲利浦下属子公司恩智浦出品的芯片缩写,目前该公司的M1芯片与国产芯片相兼容,其实M1卡也属于非接触式IC卡

    M1卡,优点是可读可写的多功能卡,缺点是:价格稍贵,感应距离短,适合非定额消费系统、停车场系统、门禁考勤系统等。

  • CPU卡

    CPU卡芯片是一个微处理器,它的功能相当于一台微型计算机。CPU卡可适用于金融、保险、交警、政府行业等多个领域,CPU卡的优点是存储空间大、读取速度快、支持一卡多用功能等特点,CPU卡从外型上与普通IC卡,射频卡并没有太大差异,但是性能上却有巨大提升,安全性和普通IC卡比,提高很多,通常CPU卡内含有随机数发生器,硬件DES,3DES加密算法等,配合CPU卡芯片上的COS操作系统,可以达到金融级的安全级别。

M1卡的数据结构

  为什么要介绍卡结构呢?因为用NFC读取卡片,获取卡片的内容的时候,你要知道卡片的数据结构,才能拿到自己想要的知识,这里就以M1卡进行讲解。

  M1卡有从0到15共16个扇区,每个扇区配备了从0到3共4个段,每个段可以保存16字节的内容。见下图

要想读取对应扇区的数据,需要知道对应扇区的秘钥,否则读取不到数据。

Android的NFC标签调度系统

  当手机发现外部NFC的标签(指含有NFC功能的设备)时,Android系统会寻找可以处理这个标签的Activity,那怎么知道哪个Activity能处理这条NFC消息呢?答案是清单文件,我们需要在清单文件中设置intent-filter。系统会分发NFC消息到设置intent-filter的Activity中,当然,接收NFC消息也有优先级之分,也是通过设置intent-filter来设置接收NFC消息的优先级的。

  NFC的标签调度系统绑定了3中intent,按优先级的高低列出,如下

  1. ACTION_NDEF_DISCOVERED:如果扫描到包含此Intent的Activity,并且可识别其类型,则使用此 Intent 启动 Activity。这是优先级最高的 Intent,NFC标签调度系统会尽可能尝试使用此 Intent 启动 Activity,在找不到这个Intent时才会尝试使用其他 Intent。
  2. ACTION_TECH_DISCOVERED:如果没有登记要处理 ACTION_NDEF_DISCOVERED Intent 的 Activity,则标签调度系统会尝试使用此 Intent 来启动应用。此外,如果扫描到的标签包含无法映射到 MIME 类型或 URI 的 NDEF 数据,或者该标签不包含 NDEF 数据,但它使用了已知的标签技术,那么也会直接启动此 Intent(无需先启动 ACTION_NDEF_DISCOVERED)。
  3. ACTION_TAG_DISCOVERED:如果没有处理 ACTION_NDEF_DISCOVERED 或者 ACTION_TECH_DISCOVERED Intent 的 Activity,则使用此 Intent 启动 Activity。

它们3者关系如下图所示

如果想处理所有的NFC标签,上面3个可以在清单文件中都进行设置。

实战演练

  前文我们已经知道了什么是NFC以及NFC的几种工作模式,也了解了市面上卡片的分类和M1卡的数据结构,基础知识已经掌握了,下面就开始进入实战演练,用Android的NFC来获取M1卡的唯一代码。

在 Android 清单中请求 NFC 访问权限

先在 AndroidManifest.xml 文件中声明以下内容,然后才能访问设备的 NFC 硬件并正确处理 NFC Intent:

  • 设置用于访问 NFC 硬件的 NFC <uses-permission>

      <uses-permission android:name="android.permission.NFC" />
    
  • 设置uses-feature 元素,以便您的应用仅在那些具备 NFC 硬件的设备的 Google Play 中显示

        <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    如果你的App不是必须要NFC功能,则uses-feature可以省略,然后再代码中通过getDefaultAdapter() 是否为 null 来判断 NFC 的可用性。

设置过滤 NFC Intent

以下示例展示了如何过滤 MIME 类型为 text/plainACTION_NDEF_DISCOVERED Intent:

    <intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="text/plain" /></intent-filter>

另外两种intent-filter的使用,可以查阅官方文档。

使用前台调度系统

前台调度系统的作用就是,在你打开一个可以处理NFC标签的Activity时,NFC的消息会优先发送给当前的Activity,不论当前的Activity设置的是哪一个intent-filter。使用前台调度系统的步骤如下

  1. 在 Activity 的 onCreate() 方法中添加以下代码:

    a. 创建一个 PendingIntent 对象。

        val intent = Intent(this, javaClass).apply {addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)}var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

    b.声明 Intent 过滤器,用来处理您要拦截的 Intent。前台调度系统会对照设备扫描标签时所获得的 Intent 来检查所指定的 Intent 过滤器。如果匹配,那么应用会处理该 Intent。如果不匹配,那么前台调度系统会回退到 Intent 调度系统。指定 Intent 过滤器和技术过滤器的 null 数组,以指明要过滤所有回退到 TAG_DISCOVERED Intent 的标签。以下代码段会处理 NDEF_DISCOVERED 的所有 MIME 类型。

        val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {try {addDataType("*/*")    /* 处理所有 MIME 类型的标签 */} catch (e: IntentFilter.MalformedMimeTypeException) {throw RuntimeException("fail", e)}}intentFiltersArray = arrayOf(ndef)

    c.设置应用要处理的一组标签技术。调用 Object.class.getName() 方法以获取要支持的技术的类。

        techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
    
  2. 替换以下 Activity 生命周期回调,并添加相应逻辑,以分别在 Activity 失去 (onPause()) 焦点和重新获得 (onResume()) 焦点时启用和停用前台调度。enableForegroundDispatch() 必须从主线程调用,并且只能在 Activity 在前台运行时调用(在 onResume() 中调用可确保这一点)。您还需要实现 onNewIntent 回调以处理扫描到的 NFC 标签中的数据。

        public override fun onPause() {super.onPause()adapter.disableForegroundDispatch(this)}public override fun onResume() {super.onResume()adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)}public override fun onNewIntent(intent: Intent) {val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)//在这里处理NFC扫描到的内容}

代码示例

  下面展示核心代码,读取M1卡并解析卡号,代码如下

//解析实体卡号
fun resolveCardNumIntent(intent: Intent?): String {if (intent == null) {return ""}//拿来装读取出来的数据,key代表扇区数,后面list存放四个块的内容//intent就是onNewIntent方法返回的那个intentval tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)val mfc = MifareClassic.get(tag)//如果当前IC卡不是这个格式的mfc就会为空if (null != mfc) {try {if (!mfc.isConnected) {//链接NFCmfc.connect()}//验证扇区密码,否则会报错(链接失败错误)val isOpen = mfc.authenticateSectorWithKeyA(0 , CARD_KEY_15)if (isOpen) {//获取扇区第一个块对应芯片存储器的位置//(我是这样理解的,因为第0扇区的这个值是4而不是0)val bIndex = mfc.sectorToBlock(0)val data = mfc.readBlock(bIndex)val byteArrToInt = DataUtils.byteArrToInt(data, 0, 4)
//                LogUtils.print("卡号: $byteArrToInt")return byteArrToInt}} catch (e: Exception) {e.printStackTrace()return ""} finally {try {mfc.close()} catch (e: IOException) {e.printStackTrace()}}}return ""
}

上面的代码注释很清晰,重点看下这段代码

val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
val mfc = MifareClassic.get(tag)//用于解析MifareClassic的实例

这里的Tag是获取卡片的Tag,NFC支持的Tag如下表

表 1. 支持的标签技术

说明
TagTechnology 这是所有标签技术类都必须实现的接口。
NfcA 提供对 NFC-A (ISO 14443-3A) 属性和 I/O 操作的访问权限。
NfcB 提供对 NFC-B (ISO 14443-3B) 属性和 I/O 操作的访问权限。
NfcF 提供对 NFC-F (JIS 6319-4) 属性和 I/O 操作的访问权限。
NfcV 提供对 NFC-V (ISO 15693) 属性和 I/O 操作的访问权限。
IsoDep 提供对 ISO-DEP (ISO 14443-4) 属性和 I/O 操作的访问权限。
Ndef 提供对 NDEF 格式的 NFC 标签上的 NDEF 数据和操作的访问权限。
NdefFormatable 为可设置为 NDEF 格式的标签提供格式化操作。

Android 设备还可以选择支持以下标签技术。

表 2. 可选择支持的标签技术

说明
MifareClassic 提供对 MIFARE Classic 属性和 I/O 操作的访问权限(如果此 Android 设备支持 MIFARE)。
MifareUltralight 提供对 MIFARE Ultralight 属性和 I/O 操作的访问权限(如果此 Android 设备支持 MIFARE)。

总结

  本文首先介绍了NFC是什么以及它的几种工作模式,然后让大家认识了一下市面上卡片的分类,也介绍了M1卡的数据结构,最后,演示了一下怎在Android中使用NFC来读取M1卡的卡号。 虽然文章没有把NFC的所有使用模式都进行讲解,但是挑了一个模式进行详细的讲解,相信阅读这篇文章后,你对Android的NFC不会那么的陌生了,其他的NFC的工作模式就由大家自行了解学习,这样才能加深印象和理解。

  最后放出本文的demo,大家可以点击这里下载

本文已由公众号“爱码者说”首发

搞懂Nfc刷卡看这篇就够了相关推荐

  1. 想要搞懂数据可视化,看这篇就够了!

    最近很多朋友跟我抱怨:为了公司数据好看,老板一个劲地想要数据可视化,以为可视化就是画画图表这么简单,可苦了自己天天加班做数据,但其实老板根本不懂可视化! 确实,数据可视化无疑是当今最火热的词,不管是做 ...

  2. 【PCB干货】是开窗还是盖油?想搞懂过孔工艺,看这篇就够了!

    过孔,即在覆铜板上钻出所需要的孔,它承接着层与层之间的导通,用于电气连接和固定器件.过孔是PCB生产至关重要且不可缺少的一环. 在PCB生产中,常见的过孔工艺有:过孔盖油.过孔塞油.过孔开窗.树脂塞孔 ...

  3. 搞懂Transformer结构,看这篇PyTorch实现就够了

    作者丨Alexander Rush 来源丨哈工大SCIR 编辑丨极市平台 下面分享一篇实验室翻译的来自哈佛大学一篇关于Transformer的详细博文. "Attention is All ...

  4. springaop事务逻辑原理_搞懂Spring AOP,这一篇就够了

    看了这篇文章,如果你还是不会用AOP来写程序,请你打我!! =.=||| 引言 Spring AOP是一个对AOP原理的一种实现方式,另外还有其他的AOP实现如AspectJ等. AOP意为面向切面编 ...

  5. 读懂SIEM建设?看这篇就够了!

    新钛云服已为您服务1443天 SIEM技术已经存在并被使用了25年以上,起初只是在海外和国内部分头部企业使用,用以解决数据孤岛.安全事件分析.运维管等问题.鉴于技术原因起初的它并不好伺候,甚至是花钱买 ...

  6. 搞定计算机网络面试,看这篇就够了

    目录 一 OSI与TCP/IP各层的结构与功能,都有哪些协议 1 应用层 2 运输层 3 网络层 4 数据链路层 5 物理层 二 TCP三次握手和四次挥手(面试常客) 为什么要三次握手 为什么要传回s ...

  7. 搞懂限流算法这一篇就够了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 TL;DR(too long don't read) 限流算法:计 ...

  8. 搞懂限流算法这一篇就够了 No.154

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 TL;DR(too long don't read) 限流算法:计数器.滑动窗口.漏桶.令牌桶 ...

  9. 搞定操作系统面试,看这篇就够了(二)

    三.死锁 必要条件 image 互斥:每个资源要么已经分配给了一个进程,要么就是可用的. 占有和等待:已经得到了某个资源的进程可以再请求新的资源. 不可抢占:已经分配给一个进程的资源不能强制性地被抢占 ...

  10. 一下子搞懂JDBC,看这篇就够了--以MySQL为例。

    一下子搞懂JDBC,看这篇就够了–以MySQL为例. 文章目录 一下子搞懂JDBC,看这篇就够了--以MySQL为例. 一.什么是JDBC? 二.JDBC的使用步骤 三.jdbc进阶--上述各个类或接 ...

最新文章

  1. linux对于大文件的解压方法
  2. 面向对象设计原则之三:里氏替换原则
  3. Centos7系统创建Docker本地仓库
  4. 轻松构建复杂数据集,永洪自服务数据查询功能详解
  5. jquery获取select选中的文本的值
  6. CI框架源码阅读笔记4 引导文件CodeIgniter.php
  7. synchronized同步方法
  8. Windows EC2 Instance 忘记密码如何重置
  9. Mysql大小写敏感问题
  10. 放弃使用 15 年的 macOS,我决定换成 Linux!
  11. Apache日志不记录图片文件设置方法
  12. python设计题60元按商品的比例平分_团体程序设计天梯赛-练习集(5分题集)Python 3...
  13. spss因子分析结果解读_AMOS进行问卷分析中效度分析之验证因子分析教程 ——【杏花开生物医药统计】...
  14. TinyPNG压缩图片的网站
  15. CH341驱动安装失败解决方法
  16. 关于零信任的 “灵魂” 12问,企业未来如何适配“零信任”?
  17. 小提琴机器人拉法_手工小提琴价格,小提琴左手持琴姿势和肩托的使用
  18. 相关系数与决定系数的关系
  19. windows server2008 R2 无法验证此程序发布者,导致VMware tool 安装失败
  20. 2022年中国农业现代化发展现状

热门文章

  1. canvas实现圆饼图,柱状图,折线图(满满的干货)
  2. c语言对英文字母循环加密,RSA加密算法(C语言实现)
  3. 2019-CS224n-Assignment2
  4. magisk下载里显示没有模块_magisk框架
  5. Centos7下载安装教程
  6. c++做病毒|教程代码
  7. vb计算机清除菜单代码,动态增减菜单用法 _VB编程语言动态增减菜单-w3school教程...
  8. AD15复制相同模块布局
  9. 计算机电源怎么设置玩游戏不卡,BIOS怎么找到显卡的设置
  10. Excel VBA生成SQL建表语句