NFC Basics(基本NFC)——翻译自developer.android.com
NFC Basics
非NDEFdata以及其它更深入技术请參见Advanced NFC。
应用程序能够通过注冊Intent过滤器(Intent Filter)来获取关注的标签信息。
由于NFC表标签的扫描是一个非常短的过程,让用户选择app会使得设备离开标签而断开连接。你应该让你的activity直接处理它关注的标签,而不要弹出activity选择的菜单。
(NFC论坛)
这些技术在Advanced NFC中介绍。我们推荐您使用NDEF标准。由于这样您能够更轻松地开发,而且获得android设备的最大的支持。假设使用其它的格式,您须要自定义协议栈来和标签通信。
当android设备扫描到包括NDEF格式数据的标签的 时候。它会解析出当中的消息,而且获取MIME类别和URI。
系统会读取NdefMessage中的第一个NdefRecord,来决定如何解析整个的NdefMessage(NdefMessage中有多个NedfRecord)。
在一个典型的NDEF格式消息里面。第一个NdefRecord包括以下几个字段:
RTD数值相应的情况请看表2。
一个Ndef message包括非常多的Ndfe Record。所以不要以为所有数据都在第一个record里面。
当MIME类型和URI没法映射为NDEF数据的时候。或者NFC标签不是以NDEF数据开头的。这样的情况下,会产生一个Tag对象,当中包括了标签的技术信息和数据负载,然后Tag对象被封装到了一个ACTION_TECH_DISCOVERED的intent中,而不再产生上面提到的那种Intent。
Type Name Format (TNF) | Mapping |
---|---|
TNF_ABSOLUTE_URI
|
URI based on the type field. |
TNF_EMPTY
|
Falls back to ACTION_TECH_DISCOVERED .
|
TNF_EXTERNAL_TYPE
|
URI based on the URN in the type field. The URN is encoded into the NDEF type field in a shortened form: <domain_name>:<service_name> . Android maps this to a URI in the form: vnd.android.nfc://ext/<domain_name>:<service_name> .
|
TNF_MIME_MEDIA
|
MIME type based on the type field. |
TNF_UNCHANGED
|
Invalid in the first record, so falls back to ACTION_TECH_DISCOVERED .
|
TNF_UNKNOWN
|
Falls back to ACTION_TECH_DISCOVERED .
|
TNF_WELL_KNOWN
|
MIME type or URI depending on the Record Type Definition (RTD), which you set in the type field. See Table 2. for more information on available RTDs and their mappings. |
Table 2. Supported RTDs for TNF_WELL_KNOWN and their mappings
Record Type Definition (RTD) | Mapping |
---|---|
RTD_ALTERNATIVE_CARRIER
|
Falls back to ACTION_TECH_DISCOVERED .
|
RTD_HANDOVER_CARRIER
|
Falls back to ACTION_TECH_DISCOVERED .
|
RTD_HANDOVER_REQUEST
|
Falls back to ACTION_TECH_DISCOVERED .
|
RTD_HANDOVER_SELECT
|
Falls back to ACTION_TECH_DISCOVERED .
|
RTD_SMART_POSTER
|
URI based on parsing the payload. |
RTD_TEXT
|
MIME type of text/plain .
|
RTD_URI
|
URI based on payload. |
假设多个应用都过滤(这里是要筛子上面的东西,能够理解为筛选,而不是漏出去的——小马)了这样的intent,就会出现activity选择器供用户选择activity。标签派发系统定义三种类型的标签,以下依照优先级从高到低排序。
<uses-permission android:name="android.permission.NFC" />
API level 10包括了广泛的读写操作的支持,还有前台的NDEF推送,API level14 提供了给其它设备推送NDEF消息的便捷办法,通过Android Beam和其它的创建NDEFrecords的便捷的方法。
<uses-sdk android:minSdkVersion="10"/>
- uses-feature 元素,在应用商店里面指示你的应用仅仅能在NFC设备上面执行。
<uses-feature android:name="android.hardware.nfc" android:required="true" />
假设你的应用仅仅是把nfc作为一个可选功能,那么你能够忽略uses-feature元素,而且在执行时候查看设备是是否支持nfc。
比方通过方法getDefaultAdapter是不是空的。
筛选NFC Intent Filtering for NFC Intents
你的应用在扫描到NFC标签的时候启动。应该在你的应用中加入一种。两种。或者三种所有类型的intent筛选。就在Android Manifest中。然而通常都是倾向于把ACTION_NDEF_DISCOVERED作为启动你应用的选项。
ACTION_TECH_DISCOVERED是第一种没有不论什么应用处理或者负载不是NDEF格式的时候的备选项。
而使用ACTION_TAG_DISCOVERED则会导致筛选太宽泛。
多数的应用都会依照优先级。先使用头两种。这样不会使得你的应用启动的太过频繁。TAG的intent作为最后的选择,在前面两种都没有应答的时候才使用。
以下的部分展示了如何筛选不同类型的intent。
ACTION_NDEF_DISCOVERED
要筛选这个类型的intent,须要声明这个类型。和数据的类型以下这个样例就指定了ACTION_NDEF_DISCOVERED的筛选。和 text/plain的MIME类型。
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="text/plain" /> </intent-filter>
以下是一种URI形式的筛选。
http://developer.android.com/index.html
.
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/><data android:scheme="http"android:host="developer.android.com"android:pathPrefix="/index.html" /> </intent-filter>
ACTION_TECH_DISCOVERED
假设你的activity筛选了ACTION_TECCH_DISCOVERED intent,你必须同一时候使用一个 tech-list集来创建一个xml文件,指明你的应用支持哪些的技术类型。假设你的支持的技术集是标签中支持的技术的子集,那么就会匹配。你能够使用getTechList()来获取标签支持的类型。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><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>
你也能够指定多个tech-list集合。每个集合都作为独立的,你的不论什么的一个list中的技术是getTechList方法返回的标签中包括的技术的子集的时候。就觉得匹配成功。这里面就是AND与和OR或的语意来匹配技术的。以下是一个吃吃NfcA和Ndef技术,或者支持NfcB和Ndef技术的集合样例。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><tech-list><tech>android.nfc.tech.NfcA</tech><tech>android.nfc.tech.Ndef</tech></tech-list> </resources><resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><tech-list><tech>android.nfc.tech.NfcB</tech><tech>android.nfc.tech.Ndef</tech></tech-list> </resources>
在你的AndroidManifest.xml文件里,在<activity>以下的<meta-data>元素里面指定上面的资源文件。如以下的样例。
<activity> ... <intent-filter><action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter><meta-data android:name="android.nfc.action.TECH_DISCOVERED"android:resource="@xml/nfc_tech_filter" /> ... </activity>
标签技术和ACTION_TECH_DISCOVERED intent的很多其它的信息。请參加Working with Supported Tag Technologies,Advance NFC文档。
ACTION_TAG_DISCOVERED
<intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
从intent中获取信息 Obtaining information from intents
public void onResume() {super.onResume();...if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {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];}}}//process the msgs array 操作获得的数组 }
你还能够从intent中获取Tag对象,当中包括了负载数据,而且你能够列举里面的技术类型。
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
创建典型的NDEF记录 Creating Common Types of NDEF Records
这个部分讲述怎样在你写入标签或者AndroidBeam通信的时候怎样创建典型的NDEF记录。从Android 4.0,即API 14開始,你能够使用createUri来自己主动帮你创建URI类型。
从Android4.1,即API 16開始,能够使用creatExternal或者createMine来创建MIME和其它的NDEF类型的record。尽量使用这些便捷的方式来避免手动创建NDEFrecord可能会发生的错误。
TNF_ABSOLUTE_URI
提示:我们推荐您使用更高效的RTD_URI来替代TNF_ABSOLUTE_URI。
NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI ,"http://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),new byte[0], new byte[0]);
筛选这个intent的筛选器例如以下:
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="http"android:host="developer.android.com"android:pathPrefix="/index.html" /> </intent-filter>
TNF_MIME_MEDIA
例如以下创建TNF_MIME_MEDIA NDEF record:
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam","Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
手动创建NdefRecord:
NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA ,"application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
上面的NDEF record的过滤器如以下这样。
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
TNF_WELL_KNOWN with RTD_TEXT
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");byte[] textBytes = payload.getBytes(utfEncoding);int utfBit = encodeInUtf8 ?
0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="text/plain" /> </intent-filter>
TNF_WELL_KNOWN with RTD_URI
使用高级方法1
NdefRecord rtdUriRecord1 = NdefRecord.createUri("http://example.com");
Uri uri = new Uri("http://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
手动创建
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix byte payload[0] = 0x01; //prefixes http://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="http"android:host="example.com"android:pathPrefix="" /> </intent-filter>
TNF_EXTERNAL_TYPE
使用高级方法:Using the createExternal()
method:
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
手动创建:Creating the NdefRecord
manually:
byte[] payload; ... NdefRecord extRecord = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType", new byte[0], payload);
过滤器:
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="vnd.android.nfc"android:host="ext"android:pathPrefix="/com.example:externalType"/> </intent-filter>
在标签部署时使用TNF_EXTERNAL_TYPE来适应更一般的NFC标签,这样能够更好的支持android设备和非android设备。
所以你仅仅须要提供一个域(比方说 样例中的example.com)和一个类型(比方说样例中的 externalType)就能够了。中间用冒号连接。
当派发TNF_EXTERNAL_TYPE类型的时候,Android会将urn:nfc:ext:example.com:externalType的urn转化为vnd.android.nfc://ext/eample.com:externalType 的URI,就是样例中的intent过滤器中定义的那样。
Android应用记录 Android Application Records
AAR在Android4.0中引入,目的是为了在扫描到标签时保证app会被启动。
AAR在NDEFrecord中嵌入了一个应用的包名。
你能够把AAR增加到NDEF message的不论什么一个NDEFrecord其中,由于android会扫描NDEF message中的每个NDEFrecord来寻找AAR。假设找到了就会基于AAR之中的包名来启动app。
假设如今设备里面没有这个app,就执行GooglePlay来開始下载app。
除非AAR是你的NedfMessage中的唯一的record,否则不要把AAR放在NdefMessage的第一个record。这是由于android系统第一个记录来推断MIME类型和标签的URI。
MIME和URI是用来产生给过滤器的intent的。
以下是一个创建AAR的样例:
NdefMessage msg = new NdefMessage(new NdefRecord[] {...,NdefRecord.createApplicationRecord("com.example.android.beam")}
向其它设备发送(Beam)NDEF消息 Beaming NDEF Messages to Other Devices
发起Beam的应用一定要在设备的前台,而接收Beam的设备应该解锁屏幕。当发起设备和接收设备的距离足够近的时候。发起的 设备会出现“点击開始Beam传送的提示”。使用者能够选择是不是Beam给接收设备信息。
很多其它请參见enableForegoundNdefPush方法。
使用Android Beam你还要知道以下几个经验:
假设你的activity也开启了“前台派发”,那么仍然能够捕获在“前台派发”中设置的intent过滤器。
当你的应用要依据当前的上下文来决定推送什么样的消息的时候。就应该使用setNdefPushMessageCallback方法。这样会更加依赖于你的用户在应用中正在做什么。
在activity中onCreate方法中调用,能够在AndroidBeamDemo中查看完整的样例。
以下的样例也能够帮助你创建一个MIME的记录:
package com.example.android.beam;import android.app.Activity; import android.content.Intent; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.NfcAdapter.CreateNdefMessageCallback; import android.nfc.NfcEvent; import android.os.Bundle; import android.os.Parcelable; import android.widget.TextView; import android.widget.Toast; import java.nio.charset.Charset;public class Beam extends Activity implements CreateNdefMessageCallback {NfcAdapter mNfcAdapter;TextView textView;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);TextView textView = (TextView) findViewById(R.id.textView);// Check for available NFC AdaptermNfcAdapter = NfcAdapter.getDefaultAdapter(this);if (mNfcAdapter == null) {Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();finish();return;}// Register callbackmNfcAdapter.setNdefPushMessageCallback(this, this);}@Overridepublic NdefMessage createNdefMessage(NfcEvent event) {String text = ("Beam me up, Android!\n\n" +"Beam Time: " + System.currentTimeMillis());NdefMessage msg = new NdefMessage(new NdefRecord[] { createMime("application/vnd.com.example.android.beam", text.getBytes())/*** The Android Application Record (AAR) is commented out. When a device* receives a push with an AAR in it, the application specified in the AAR* is guaranteed to run. The AAR overrides the tag dispatch system.* You can add it back in to guarantee that this* activity starts when receiving a beamed message. For now, this code* uses the tag dispatch system.*///,NdefRecord.createApplicationRecord("com.example.android.beam")});return msg;}@Overridepublic void onResume() {super.onResume();// Check to see that the Activity started due to an Android Beamif (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {processIntent(getIntent());}}@Overridepublic void onNewIntent(Intent intent) {// onResume gets called after this to handle the intentsetIntent(intent);}/*** Parses the NDEF Message from the intent and prints to the TextView*/void processIntent(Intent intent) {textView = (TextView) findViewById(R.id.textView);Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);// only one message sent during the beamNdefMessage msg = (NdefMessage) rawMsgs[0];// record 0 contains the MIME type, record 1 is the AAR, if presenttextView.setText(new String(msg.getRecords()[0].getPayload()));} }
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="application/vnd.com.example.android.beam"/> </intent-filter>
AAR没有activity级别的标志。
而且另一些设备不支持AAR,你应该仍然在NDEFmessage的第一个NDEFRecord中嵌入指示信息,而且用过滤器来获取。以防万一。创建record的方法详情请參见Creating common Types fo NDEF records。
NFC Basics(基本NFC)——翻译自developer.android.com相关推荐
- Android NFC Basics
译自 https://developer.android.google.cn/guide/topics/connectivity/nfc/nfc.html This document describe ...
- Android NFC技术(三)——初次开发Android NFC你须知道NdefMessage和NdefRecord
Android NFC技术(三)--初次开发Android NFC你须知道NdefMessage和NdefRecord 这最近也是有好多天没写博客了,除了到处张罗着搬家之外,依旧还是许许多多的琐事阻碍 ...
- android nfc 鸡肋,手机NFC真的鸡肋吗?这些功能很实用
随着智能手机功能的逐渐强大,NFC功能已经出现在了很多手机中,今天老瓦就和大家聊聊手机NFC的那些事儿. NFC又称近场通信,即近距离无线通讯技术.在单一的芯片上结合读卡器.点对点的功能,可以实现近距 ...
- 【翻译】(5)Android.mk File
----------------- 英文文档见android-ndk-r5b的documentation.html 属于Android Native Development Kit (NDK)的一部分 ...
- nfc是什么?nfc功能是什么?
http://android.tgbus.com/lab/software/201208/447420.shtml nfc是什么?nfc功能是什么?出现在我们手机上的nfc功能怎么用?下面请看今天小编 ...
- ExternalDocumentationLinkImpl(url=https://developer.android.com/reference/, packageListUrl=https://d
dokka 问题 java.lang.RuntimeException: Exception while loading package-list from ExternalDocumentation ...
- 访问:source.android.com和developer.android.com
1.不可访问 https://source.android.com https://developer.android.com2.可以访问 https://source.android.google. ...
- pn532检测不到nfc设备_华为、小米又增回NFC功能,苹果却一直无NFC功能,NFC能否成为关键?...
曾几何时,被众人唱衰的NFC功能又被悄悄的加入到各大手机厂商发布的几款新机中.当初NFC模块刚加入到手机的时候能成为一大卖点之一,然而因外部技术的迭代更新速度不够快,手机NFC功能变得鸡肋了起来,如今 ...
- NFC Forum发布NFC数据交换格式(NDEF)规范
为实现NFC标签.NFC设备以及NFC设备之间的交互通信,NFC论坛(NFC Forum)定义了称为NFC数据交换格式(NDEF)的通用数据格式. 为实现NFC标签.NFC设备以及NFC设备之间的交互 ...
最新文章
- python编程课-python编程课---turtle
- PMCAFF | 阿里PM的可用性测试秘籍:有理有据的用户体验优化
- 850 USB 烧录模式
- 网址出现error.aspx?aspxerrorpath=404.htm?aspxerrorpath=的原因及解决办法转
- HTML网页设计综合题,网页设计(Html5)试题C卷
- 计算机函数sun怎么用,excel函数怎么使用
- 平安夜关于苹果的题目——1705. 吃苹果的最大数目
- ES3~ES7的数组方法
- 惠普136w耗材贵吗_不妨试一试:惠普打印机136w与m30w哪个好?有没有区别?到底坑不坑?...
- 一文详解传统金融与数字资产衍生品的区别
- 一文带你走进车联网安全
- ETL: Extraction Transformation Loading
- left join 多表关联查询
- 领带的10种打法图解
- 求帮忙解决图灵机器人运行不回复的问题
- Java--面包师与消费者2(发送线程与接收线程)
- 解决 macOS Monterey 启动不了泰拉瑞亚 (sdl2)
- 轻松进行SOLIDWORKS基础绘图
- 如何通过maven打包可执行jar包
- Box2D v2.1.0用户手册(8)——关节(Joints)