Android NFC

    Android中NFC知识介绍

    近场通信(NFC)是一种短距离无线技术,通常要求距离为4cm或更低以启动连接。NFC允许你在NFC标签和android驱动的设备之间,或者在两个android驱动的设备之间共享少量的数据。

    简单的标签只提供读和写的功能,有时使用一个可编程的区域使卡片只读。更复杂的标签提供数学运算,并有加密硬件来认证对一个扇区的访问。最复杂的标签包含操作环境,允许通过代码与在标签进行复杂的交互。存储在标签中的数据也可以用多种格式编写,但是Android框架api大多都是基于NDEF标准(NFC数据交换格式)。

    根据Google官方文档的介绍,具有NFC的安卓设备同时支持三种主要的操作方式:

  • Reader/writer mode, allowing the NFC device to read and/or write passive NFC tags and stickers.
  • P2P mode, allowing the NFC device to exchange data with other NFC peers; this operation mode is used by Android Beam.
  • Card emulation mode, allowing the NFC device itself to act as an NFC card. The emulated NFC card can then be accessed by an external NFC reader, such as an NFC point-of-sale terminal.
    本文主要是针对第一种操作方式作介绍。

    Android NFC 开发中的几个类:

    NfcManager用来管理Android设备中所有NFC Adapter,通过getSystemService(Class)来获取它的实例。

    NfcAdapter手机的NFC硬件设备,代表了设备的NFC适配器,是NFC操作的入口,大部分Android设备只支持一个NFC Adapter,可以通过getDefaultAdapter()、getDefaultAdapter(android.content.Context)来获取它的实例。

    NdefMessage:表示一个NDEF数据的,这是在设备和标签之间传输数据的“records”的标准格式。程序可以通过action“ACTION_TAG_DISCOVERED”来接收这些数据。

   NdefRecord 表示一个record,该record在NdefMessage中传递,并描述共享数据的类型和数据本身。

简单说一下NDEF格式:一个NDEF格式的标签使用一个NdefMessage来包装,一个NdefMessage由0个或多个NdefRecord组成,其中有各种各样的NdefRecord,比如放Url的,放文本信息的等等,这里介绍的是放文本信息的NdefRecord的格式:

    一个NdefRecord由四个字段构成:

3-bit TNF:类型名称格式可变长度类型RTD:记录类型定义可变长度ID:唯一标识该记录可变长度的负载:就是文本信息

    Tag代表一个被动式NFC对象,比如一张公交卡,Tag可以理解成能被手机NFC读写的对象。当Android检测到一个Tag时,会创建一个Tag对象,将其放在Intent对象中,然后发送到相应的Activity。

    详见:https://developer.android.com/guide/topics/connectivity/nfc/nfc.html#p2p

    Android 支持的标签技术

    当使用NFC标签和android驱动的设备时,用来读取和写入标签数据的主要格式是NDEF。当设备扫描带有NDEF数据的标签时,Android提供了解析消息的支持,并在可能的情况下将其发送到NDEF消息中。但是,当您扫描一个不包含NDEF数据或NDEF数据不能映射到MIME类型或URI的标记时,会出现一些情况。在这些情况下,需要直接与标签进行通信,并使用自己的协议(在原始字节中)读取和写入它。Android为这些用例提供了通用的支持

    表 1.  支持的Tag技术
描述
TagTechnology这个接口是下面所有tag technology类必须实现的。
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提供对那些被格式化为NDEFtag的数据的访问和其他操作
NdefFormatable对那些可以被格式化成NDEF格式的tag提供一个格式化的操作
下面的Tag技术不要求被Android的供电设备支持。

    表 2. 可选的支持的Tag技术

描述
MifareClassic如果android设备支持MIFARE,提供对MIFARE Classic目标的属性和I/O操作。
MifareUltralight如果android设备支持MIFARE,提供对MIFARE Ultralight目标的属性和I/O操作。
关于Android系统驱动的设备所支持的标签技术详见:
https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc.htm

    Android NFC调度系统

NFC调度是指手机检测到NFC对象后如何处理,调度系统分为前台调度系统(Foreground Dispatch System)和标签调度系统(NFC Tag Dispatch System)

   1) 前台调度系统

NFC前台调度系统是一种用于在运行的程序中(前台呈现的Activity)处理Tag的技术,即前台调度系统允许Activity拦截Intent对象,并且声明该Activity的优先级比其他的处理Intent对象的Activity高。前台调度系统在一些涉及需要在前台呈现的页面中直接获取或推送NFC信息时十分方便。本文的示例就是使用前台调度。

   2) NFC标签调度系统

当标签分派系统完成创建一个封装NFC标签及其标签信息的意图时,它将意图发送到一个可以处理该意图的应用程。当存在多个可以处理该Tag信息的application时,系统会弹出一个Activity Chooser,供用户选择哪个application来处理这个意图。标签调度系统定义了3种意图,按照优先级由高到低分别为:

  • ACTION_NDEF_DISCOVERED: This intent is used to start an Activity when a tag that contains an NDEF payload is scanned and is of a recognized type. This is the highest priority intent, and the tag dispatch system tries to start an Activity with this intent before any other intent, whenever possible.
  • ACTION_TECH_DISCOVERED:  If no activities register to handle the ACTION_NDEF_DISCOVERED intent, the tag dispatch system tries to start an application with this intent. This intent is also directly started (without starting ACTION_NDEF_DISCOVERED first) if the tag that is scanned contains NDEF data that cannot be mapped to a MIME type or URI, or if the tag does not contain NDEF data but is of a known tag technology.
  • ACTION_TAG_DISCOVERED: This intent is started if no activities handle the ACTION_NDEF_DISCOVERED or ACTION_TECH_DISCOVERED intents.

标签分派系统的基本流程:

详见:https://developer.android.com/guide/topics/connectivity/nfc/nfc.html#tag-dispatch

    Android NFC编程示例(使用前台调度系统)

package com.bugull.nfctest;

import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

/**
 * @author kk
 */
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private NfcAdapter mNfcAdapter;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.tv_nfc_detail);
        mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
        if (mNfcAdapter == null) {
            Toast.makeText(this, "该设备不支持nfc", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        if (!mNfcAdapter.isEnabled()) {
            startActivity(new Intent("android.settings.NFC_SETTINGS"));
            Toast.makeText(this, "设备未开启nfc", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mNfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter[] intentFilters = new IntentFilter[]{};
        mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            Tag iTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            mTextView.setText(TagReader.readTag(iTag, intent));
        }
    }
}
    效果:

源码下载:

https://github.com/yingka/nfc-reader

参考资料:

https://nfc-forum.org/

https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc.html#foreground-dispatch

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值