视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
nfc介绍以及android应用API
2025-10-03 05:29:19 责编:小OO
文档
NFC(近场通信)

NFC是一套短距离的无线通信,通常距离是4厘米或更短。NFC工作频率是13.56M Hz,传输速率是106kbit/s 到848kbit/s. NFC总是在一个发起者和一个被动目标之间发生。发起者发出近场无线电波,这个近场可以给被动目标供电。这些被动的目标包括不需要电源的标签,卡,也可以是有电源的设备。

与其他无线通信技术比较, 例如蓝牙和WiFi, NFC提供更低带宽和距离,并且低成本,不需要供电,不需要实现匹配,整个通信过程仅仅是短短的靠近一秒就能完成。

一个带有NFC支持的android设备通常是一个发起者。也可以作为NFC的读写设备。他将检测NFC tags并且打开一个Activity来处理. Android 2.3.3还有支持有限的P2P。

Tags分很多种,其中简单的只提供读写段,有的只能读。复杂的tags可以支持一些运算,加密来控制对tags里数据段的读写。甚至一些tags上有简单的操作系统,允许一些复杂的交互和可以执行一些代码。

API概览

Android.nfc  package包含顶层类用来与本地NFC适配器交互. 这些类可以表示被检测到的tags和用NDEF数据格式。

ClassDescription
NfcManager一个NFC adapter的管理器,可以列出所有此android设备支持的NFC adapter.只不过大部分android 设备只有一个NFC adapter,所以你大部分情况下可以直接用静态方法getDefaultAdapter(context)来取适配器。

NfcAdapter表示本设备的NFC adapter,可以定义Intent来请求将系统检测到tags的提醒发送到你的Activity.并提供方法去注册前台tag提醒发布和前台NDEF推送。 前台NDEF推送是当前android版本唯一支持的p2p NFC通信方式。

NdefMessageandNdefRecord

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对象。

android.nfc.tech package 包含那些对tag查询属性和进行I/O操作的类。这些类分别标示一个tag支持的不同的NFC技术标准。

ClassDescription
TagTechnology这个接口是下面所有tag technology类必须实现的。

NfcA支持ISO 14443-3A 标准的操作。Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.

NfcBProvides access to NFC-B (ISO 14443-3B) properties and I/O operations.
NfcFProvides access to NFC-F (JIS 6319-4) properties and I/O operations.
NfcVProvides access to NFC-V (ISO 15693) properties and I/O operations.
IsoDepProvides 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操作。

声明Android Manifest.xml的元素

在你能访问一个设备的NFC硬件和正确的处理NFC的Intent之前,需要在AndroidManifest.xml中先声明下面的项:

1.     NFC使用  元素来访问NFC硬件:

2.     最小SDK版本需要设置正确,API level 9只包含有限的tag支持,包括:

    .通过ACTION_TAG_DISCOVERED来发布Tag信息

    .只有通过EXTRA_NDEF_MESSAGES扩展来访问NDEF消息

    .其他的tag属性和I/O操作都不支持

所以你可能想要用API level 10来实现对tag的广泛的读写支持。

3.     uses-feature 元素定义:你的程序可以再android市场里显示有NFC硬件。

4.      NFC intent filter告诉android系统你的activity能处理NFC数据,可以定义1个或多个intent filter:

  

  

  

                  android:resource="@xml/nfc_tech_filter.xml" />

  

上边3个intent filters 有优先级,更多信息可以看下面的Tag发布系统

也可以看NFCDemo例子的 AndroidManifest.xml来有个更深的理解。

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发布系统。

使用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就会被调用。例如想处理一个包含plain text 的 NDEF_DISCOVERED intent ,你要按照如下定义AndroidManifest.xml file:

    

    

如果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列表。更多细节请看下面的Specifying tag technologies to handle.

∙         android.nfc.action.TAG_DISCOVERED: 如果没有一个activity处理_DISCOVERED and TECH_DISCOVEREDintents或者tag被检测为未知的,那么此Intent将会被启动。

Specifying tag technologies to handle指定处理的technologies

假如你的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。

下面是一个资源文件例子,定义了所有的technologies. 你可以根据需要删掉不需要的项,将此文件以任意名字+.xml保存到/res/xml文件夹.

    

        android.nfc.tech.IsoDep

        android.nfc.tech.NfcA        

        android.nfc.tech.NfcB

        android.nfc.tech.NfcF

        android.nfc.tech.NfcV

        android.nfc.tech.Ndef

        android.nfc.tech.NdefFormatable

        android.nfc.tech.MifareClassic

        android.nfc.tech.MifareUltralight

    

你也可以指定多个tech-list集合,每个集合都认做的。如果任何单个tech-list集合是getTechList()返回的technologies集合的子集,那么你的Activity将被认为匹配了。这个还提供’与’和’或’操作。下面的例子表示支持NfcA和NDef的卡,或者支持NfcB和NDef的卡:

    

        android.nfc.tech.NfcA        

        android.nfc.tech.Ndef

    

    

        android.nfc.tech.NfcB        

        android.nfc.tech.Ndef

    

在 AndroidManifest.xml 文件中, 指定这个tech-list资源文件的方法是在 元素中创建元素,例如下面例子:

...

    

    android:resource="@xml/nfc_tech_filter" />

...

使用前台发布系统Using the foreground dispatch system

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

1.     添加下列代码到Activity的onCreate() 方法里

a.     创建一个 PendingIntent 对象, 这样Android系统就能在一个tag被检测到时定位到这个对象

PendingIntent pendingIntent = PendingIntent.getActivity(

    this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

b.    在Intent filters里声明你想要处理的Intent,一个tag被检测到时先检查前台发布系统,如果前台Activity符合Intent filter的要求,那么前台的Activity的将处理此Intent。如果不符合,前台发布系统将Intent转到Intent发布系统。如果指定了null的Intent filters,当任意tag被检测到时,你将收到TAG_DISCOVERED intent。因此请注意你应该只处理你想要的Intent。

    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);

        try {

            ndef.addDataType("*/*");    /* Handles all MIME based dispatches. 

                                           You should specify only the ones that you need. */

        }

        catch (MalformedMimeTypeException e) {

            throw new RuntimeException("fail", e);

        }

        intentFiltersArray = new IntentFilter[] {

                ndef,

        };

c.     设置一个你程序要处理的Tag technologies的列表,调用Object.class.getName() 方法来获得你想要支持处理的technology类。

  techListsArray = new String[][] { new String[] { NfcF.class.getName() } };

 

2.     覆盖下面的方法来打开或关闭前台发布系统。比如onPause()和onResume()方法。必须在主线程里调用enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][]) 而且Activity在前台(可以在onResume()里调用来保证这点)。你也要覆盖onNewIntent回调来处理得到的NFC tag数据。

public void onPause() {

    super.onPause();

    mAdapter.disableForegroundDispatch(this);

}   

public void onResume() {

    super.onResume();

    mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray,techListsArray);

}

public void onNewIntent(Intent intent) {

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

    //do something with tagFromIntent

}

See the ForegroundDispatch sample from API Demos for the complete sample.

使用NFC tag上的数据

NFC tag上的数据是以字节存放,所以你可以将其转换成其他你想要的格式。当往tag写东西时,你必须以字节格式来写。Android提供API来帮助写符合NDEF标准的信息。使用此标准能保证你的数据在往tag写时能被所有Android NFC设备支持。然而,很多tag使用他们自己的标准来存储数据,这些标准也被Android支持。但你必须自己实现协议栈来读写这些tag。你可以在android.nfc.tech里找到所有支持的technologies,并且可以在TagTechnology接口里对technology有个了解。这一段是简单介绍在android系统里怎样使用NDEF 消息。这不意味着是一个完整的NDEF功能的介绍。但标出了主要需要注意和使用的东西。

为了方便使用NDEF消息,android提供NdefRecord 和 NdefMessage来包装原始字节数据为NDEF消息。一个NdefMessage是保存0个或多个NdefRecords的容器。每个NdefRecord有自己的唯一类型名字格式,记录类型和ID来与其他记录区分开。你可以存储不同类型的记录,不同的长度到同一个 NdefMessage。NFC tag容量的决定你的NdefMessage的大小。

那些支持Ndef和NdefFormatable技术的tag可以返回和接受NdefMessage对象为参数来进行读写操作。你需要创建你自己的逻辑来为其他在android.nfc.tech的tag技术实现读写字节的操作。

你可以从NFC Forum(http://www.nfc-forum.org/specs/)下载NDEF消息标准的技术文档,比如纯文本和智慧型海报. NFCDemo例子里声明了纯文本和智慧型海报的NDef 消息。

读一个NFC tag

当一个NFC tag靠近一个NFC设备,一个相应的Intent将在设备上被创建。然后通知合适的程序来处理此Intent。

下面的方法处理TAG_DISCOVERED intent并且使用迭代器来获得包含在NDEF tag负载的数据

NdefMessage[] getNdefMessages(Intent intent) {

    // Parse the intent

    NdefMessage[] msgs = null;

    String action = intent.getAction();

    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {

        Parcelable[] rawMsgs =intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

        if (rawMsgs != null) {

            msgs = new NdefMessage[rawMsgs.length];

            for (int i = 0; i < rawMsgs.length; i++) {

                msgs[i] = (NdefMessage) rawMsgs[i];

            }

        }

        else {

        // Unknown tag type

            byte[] empty = new byte[] {};

            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty,empty);

            NdefMessage msg = new NdefMessage(new NdefRecord[] {record});

            msgs = new NdefMessage[] {msg};

        }

    }        

    else {

        Log.e(TAG, "Unknown intent " + intent);

        finish();

    }

    return msgs;

}

请记住NFC设备读到的数据是byte类型,所以你可能需要将他转成其他格式来呈现给用户。NFCDemo例子展示了怎样用com.example.android.nfc.record中的类来解析NDEF消息,比如纯文本和智慧型海报。

写NFC tag

往NFC tag写东西涉及到构造一个NDEF 消息和使用与tag匹配的Tag技术。下面的代码展示怎样写一个简单的文本到NdefFormatable tag:

NdefFormatable tag = NdefFormatable.get(t);

Locale locale = Locale.US;

final byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);

String text = "Tag, you're it!";

final byte[] textBytes = text.getBytes(Charsets.UTF_8);

final int utfBit = 0;

final char status = (char) (utfBit + langBytes.length);

final byte[] data = Bytes.concat(new byte[] {(byte) status}, langBytes, textBytes);

NdefRecord record = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, newbyte[0], data);

try {

    NdefRecord[] records = {text};

    NdefMessage message = new NdefMessage(records);

    tag.connect();

    tag.format(message);

}

catch (Exception e){

    //do error handling

}

点对点的数据交换

前台推送技术支持简单点对点的数据交换,你可以用enableForegroundNdefPush(Activity, NdefMessage) 方法来打开此功能. 为了用这个功能:

∙         推送数据的Activity必须是前台Activity。

∙         你必须将你要发送的数据封装到NdefMessage对象里。

∙         接收推送数据的设备必须支持com.android.npp  NDEF推送协议,这个对于Android设备是可选的

假如你的Activity打开了前台推送功能并且位于前台,这时标准的Intent发布系统是禁止的。然而,如果你的Activity允许前台发布系统,那么此时检测tag的功能仍然是可用的,不过只适用于前台发布系统。

要打开前台推送:

1.     创建一个你要推送给其他NFC设备的包含NdefRecords的NdefMessage。

2.     在你的Activity里实现onResume() 和 onPause() 的回调来正确处理前台推送的生命周期。你必须在你的Activity位于前台并在主线程里调用enableForegroundNdefPush(Activity, NdefMessage) (可以在onResume()里调用来保证这点).

public void onResume() {

    super.onResume();

    if (mAdapter != null)

        mAdapter.enableForegroundNdefPush(this, myNdefMessage);

}

public void onPause() {

    super.onPause();

    if (mAdapter != null)

        mAdapter.disableForegroundNdefPush(this);

}

当Activity位于前台,你可以靠近另外一个NFC设备来推送数据。请参考例子ForegroundNdefPush来了解点对点数据交换。下载本文

显示全文
专题