Android NFC开发详细介绍一(理论篇)

作者: 程思扬 | 来源:发表于2019-01-18 15:25 被阅读133次

    大家在做nfc开发之前可以看一下我的上篇文章区分IC卡和ID卡

    Near Field Communication (NFC) 为一短距离无线通信技术,通常有效通讯距离为4厘米以内。NFC工作频率为13.65 兆赫兹,通信速率为106 kbit/秒到 848kbit/秒,NFC手机相比普通手机来说,NFC整合了非接触式读卡器、非接触式智能卡和点对点(Peer-to—Peer)通信功能,为消费者开创了全新的便捷生活方式。手机和NFC技术的结合,将会给消费者提供极大的生活便利,例如移动支付、位置服务信息、身份识别、公共交通卡等应用,在医疗保健、优惠券、智能海报等许多领域有也有巨大的应用潜力。

    一 、nfc的三种工作模式

    这里给出官方文档的链接 大家可以看一下

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

    2. 仿真卡模式
      数据在支持NFC的手机或其它电子设备中,可以简单理解成“刷手机”。本质上就是将支持NFC的手机或其它电子设备当成借记卡、公交卡、门禁卡等IC卡使用。基本原理是将相应IC卡中的信息凭证封装成数据包存储在支持NFC的外设中 。
      在使用时还需要一个NFC射频器(相当于刷卡器)。将手机靠近NFC射频器,手机就会接收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的电脑,并进行相应的处理(如电子转帐、开门等操作)。

    3. 点对点模式
      该模式与蓝牙、红外差不多,用于不同NFC设备之间进行数据交换,不过这个模式已经没有有“刷”的感觉了。其有效距离一般不能超过4厘米,但传输建立速度要比红外和蓝牙技术快很多,传输速度比红外块得多,如过双方都使用Android4.2,NFC会直接利用蓝牙传输。这种技术被称为Android Beam。所以使用Android Beam传输数据的两部设备不再限于4厘米之内。
      点对点模式的典型应用是两部支持NFC的手机或平板电脑实现数据的点对点传输,例如,交换图片或同步设备联系人。因此,通过NFC,多个设备如数字相机,计算机,手机之间,都可以快速连接,并交换资料或者服务。

    花了点时间,下面用表格写出NFC、蓝牙和红外之间的差异:

    对比项 NFC 蓝牙 红外
    网络类型 点对点 单点对多点 点对点
    有效距离 <=0.1m <=10m,最新的蓝牙4.0有效距离可达100m 一般在1m以内,热技术连接,不稳定
    传输速度 最大424kbps 24Mbps 最大慢速115.2kbps,快速4Mbps
    建立时间 <0.1s 6s 0.5s
    安全性 安全,硬件实现 安全,软件实现 不安全,使用IRFM时除外
    通信模式 主动-主动/被动 主动-主动 主动-主动
    成本

    二、Android对NFC的支持

    不同的NFC标签之间差异很大,有的只支持简单的读写操作,有时还会采用支持一次性写入的芯片,将NFC标签设计成只读的。当然,也存在一些复杂的NFC标签,例如,有一些NFC标签可以通过硬件加密的方式限制对某一区域的访问。还有一些标签自带操作环境,允许NFC设备与这些标签进行更复杂的交互。这些标签中的数据也会采用不同的格式。
    ==但Android SDK API主要支持NFC论坛标准(Forum Standard),这种标准被称为NDEF(NFC Data Exchange Format,NFC数据交换格式)==

    三、API概览 Class Description

    Class Description
    NfcManager 一个NFC adapter的管理器,可以列出所有此android设备支持的NFC adapter.只不过大部分android 设备只有一个NFC adapter,所以你大部分情况下可以直接用静态方法 getDefaultAdapter(context)来取适配器。
    NfcAdapter 表示本设备的NFC adapter,可以定义Intent来请求将系统检测到tags的提醒发送到你的Activity.并提供方法去注册前台tag提醒发布和前台NDEF推送。 前台NDEF推送是当前android版本唯一支持的p2p NFC通信方式。
    NdefMessage,NdefRecord NDEF是NFC论坛定义的数据结构,用来有效的存数据到NFC tags.比如文本,URL,和其他MIME类型。一个NdefMessage扮演一个容器,这个容器存哪些发送和读到的数据。一个NdefMessage对象包含0或多个NdefRecord,每个NDEF record有一个类型,比如文本,URL,智慧型海报/广告,或其他MIME数据。在NDEFMessage里的第一个NfcRecord的类型用来发送tag到一个android设备上的activity.
    Tag 标示一个被动的NFC目标,比如tag,card,钥匙挂扣,甚至是一个电话模拟的的NFC卡. 当一个tag被检测到,一个tag对象将被创建并且封装到一个Intent里,然后NFC 发布系统将这个Intent用startActivity发送到注册了接受这种Intent的activity里。你可以用getTechList()方法来得到这个tag支持的技术细节和创建一个android.nfc.tech提供的相应的TagTechnology对象。

    四、Tag支持的技术标准

    Class Description
    TagTechnology 这个接口是下面所有tag technology类必须实现的。
    NfcA 支持ISO 14443-3A 标准的操作。Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.
    NfcB Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.
    NfcF Provides access to NFC-F (JIS 6319-4) properties and I/O operations.
    NfcV Provides access to NFC-V (ISO 15693) properties and I/O operations.
    IsoDep Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.
    Ndef 提供对那些被格式化为NDEF的tag的数据的访问和其他操作。 Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
    NdefFormatable 对那些可以被格式化成NDEF格式的tag提供一个格式化的操作
    MifareClassic 如果android设备支持MIFARE,提供对MIFARE Classic目标的属性和I/O操作。
    MifareUltralight 如果android设备支持MIFARE,提供对MIFARE Ultralight目标的属性和I/O操作。

    五、Tag发布系统

    当android设备扫描到一个NFC tag,通用的行为是自动找最合适的Activity会处理这个tag Intent而不需要用户来选择哪个Activity来处理。因为设备扫描NFC tags是在很短的范围和时间,如果让用户选择的话,那就有可能需要移动设备,这样将会打断这个扫描过程。你应该开发你只处理需要处理的tags的Activity,以防止让用户选择使用哪个Activity来处理的情况。Android提供两个系统来帮助你正确的识别一个NFC tag是否是你的Activity想要处理的:Intent发布系统和前台Activity发布系统。

    Intent发布系统检查所有Activities的intent filters,找出那些定义了可以处理此tag的Activity,如果有多个Activity都配置了处理同一个tag Intent,那么将使用Activity选择器来让用户选择使用哪个Activity。用户选择之后,将使用选择的Activity来处理此Intent.

    前台发布系统允许一个Activity覆盖掉Intent发布系统而首先处理此tag Intent,这要求你将要处理Tag Intent的Activity运行在前台,这样当一个NFC tag被扫描到,系统先检测前台的Activity是否支持处理此Intent,如果支持,即将此Intent传给此Activity,如果不支持,则转到Intent发布系统。

    5.1使用Intent发布系统

    Intent发布系统指定了3个intent有不同的优先级。通常当一个tag被检测到之后,Intent就被启动(start)了,这个启动遵循以下行为

    • android.nfc.action.NDEF_DISCOVERED: 这个intent是在一个包含NDEF负载的tag被检测到时启动,这是最高优先级的intent, android系统不会让你指定一个Intent能处理所有的NFC数据类型,你必须在AndroidManifest.xml中指定与NFC tag对应的元素,这样当扫描到的tag传过来的数据类型与你定义的相匹配时,你的Activity就会被调用。
    <activity android:name=".NdefActivity"
               android:launchMode="singleTop"
               android:label="NDEF格式"
               > 
               <intent-filter>  
                 <action android:name="android.nfc.action.NDEF_DISCOVERED"/>    
                 <category android:name="android.intent.category.DEFAULT"/> 
                </intent-filter>
              </activity>
    

    如果NDEF_DISCOVERED intent 已经被启动,TECH_DISCOVERED 和 TAG_DISCOVERED intents 将不会被启动。假如一个未知的tag或者不包含NDEF负载的tag被检测到,此Intent就不会被启动。

    • android.nfc.action.TECH_DISCOVERED: 如果 NDEF_DISCOVERED intent没启动或者没有一个Activity的filter检测NDEF_DISCOVERED ,并且此tag是已知的,那么此TECH_DISCOVERED Intent将会启动. TECH_DISCOVERED intent要求你在一个资源文件里(xml)里指定你要支持technologies列表。
    <activity android:name=".MifareClassicActivity"
                android:launchMode="singleTop"
                android:label="读写MIFARECLASSIC格式"
                > 
             <intent-filter>
              <action android:name="android.nfc.action.TECH_DISCOVERED"/> 
                <category android:name="android.intent.category.DEFAULT"/> </intent-filter> 
               
                <meta-data  
               android:name="android.nfc.action.TECH_DISCOVERED"
               android:resource="@xml/tech_list"
                />
          </activity>
    
    • android.nfc.action.TAG_DISCOVERED: 如果没有一个activity处理_DISCOVERED and TECH_DISCOVERED intents或者tag被检测为未知的,那么此Intent将会被启动。

    假如你的Activity在AndroidManifest.xml文件里声明了处理android.nfc.action.TECH_DISCOVERED intent ,你必须创建一个Xml格式的资源文件,并加上你的activity支持的technologies到tech-list集合里。这样你的activity将被认作能处理这些tech-list的处理者,如果tag使用的technology属于你的定义的list里,你的Activity将接收此Intent。你可以用getTechList()来获得tag支持的technologies。
    例如:如果一个tag被检测到支持MifareClassic, NdefFormatable, 和 NfcA,你的tech-list集合必须指定了其中的一项或者多项来保证你的Activity能处理此Intent。
    你也可以指定多个tech-list集合,每个集合都认做独立的。如果任何单个tech-list集合是getTechList()返回的technologies集合的子集,那么你的Activity将被认为匹配了。这个还提供’与’和’或’操作。
    tech_filter.xml

    <?xml version="1.0" encoding="utf-8"?> 
    <resources> 
    <!--多个<tech-list>元素之间是OR关系,<tech-list>元素中的
    <tech>是AND关系,只要任何单个tech-list集合是getTechList()返回的technologies集合的子集,那么你的Activity将被认为匹配了--> 
    
      <tech-list> 
        <tech>android.nfc.tech.Ndef</tech> 
        <tech>android.nfc.tech.MifareClassic</tech> 
    </tech-list> 
    
    <!--或--> 
    
      <tech-list> 
        <tech>android.nfc.tech.IsoDep</tech> 
        <tech>android.nfc.tech.NfcA</tech> 
        <tech>android.nfc.tech.NfcB</tech> 
        <tech>android.nfc.tech.NfcF</tech> 
        <tech>android.nfc.tech.NfcV</tech> 
        <tech>android.nfc.tech.Ndef</tech> 
        <tech>android.nfc.tech.NdefFormatable</tech> 
        <tech>android.nfc.tech.MifareClassic</tech> 
        <tech>android.nfc.tech.MifareUltralight</tech> 
      </tech-list> 
    </resources>
    

    5.2使用前台发布系统

    前台发布系统允许一个Activity 拦截一个tag Intent 获得最高优先级的处理,这种方式很容易使用和实现:

    1. 在OnCreate()方法中创建一个 PendingIntent对象, 这样Android系统就能在一个tag被检测到时定位到这个对象
    PendingIntent pendingIntent = PendingIntent.getActivity(
     this, 0, new Intent(this, getClass())
    .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    

    ==launchMode设为singleTop,这样无论NFC标签靠近手机多少次,保障只有一个Activity实例。(除一次靠近调用OnCreate()方法外,标签每一次靠近都会调用OnNewIntent()方法。)==

    2. 在主线程里调用enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][])而且Activity在前台(可以在onResume()里调用来保证这点)
    //页面获取到焦点 
      @Override 
      protected void onResume() {
       super.onResume(); 
       if (mNfcAdapter!=null){   
       mNfcAdapter.enableForegroundDispatch(
       this,mPendingIntent,null,null);
     //打开前台发布系统,使页面优于其它nfc处理 
     } 
    }
    //页面失去焦点 
    @Override 
      protected void onPause() { 
       super.onPause(); 
       if(mNfcAdapter!=null){ 
       mNfcAdapter.disableForegroundDispatch(this);
    //关闭前台发布系统
     } 
    }
    
    3.在OnNewIntent中获取Tag对象
    @Override
    protected void onNewIntent(Intent intent) {   
    super.onNewIntent(intent); 
     mTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
     String[] techList=mTag.getTechList();  
     System.out.println("标签支持的tachnology类型:"); 
     for (String tech:techList){ 
     System.out.println(tech); 
     } 
    }
    

    以上,是关于NFC的基础知识,下一篇我们将实现对NFC Ndef标签和MifareClassic标签的读写操作,大家有什么意见或问题欢迎留言。

    相关文章

      网友评论

        本文标题:Android NFC开发详细介绍一(理论篇)

        本文链接:https://www.haomeiwen.com/subject/kvundqtx.html