nfc入门
来源:互联网 发布:paperpass查重软件 编辑:程序博客网 时间:2024/06/06 00:30
基础
参考
利用nfc读取公交卡
nfc:近距离无线通信(Near Field Communication),距离一般要小于4cm。android设备(需要支持nfc技术)和nfc设备(文档中称为tag)进行少量的数据交换。
权限及feature配置
需要nfc权限,如下:
<uses-permission android:name="android.permission.NFC"/>也可以配置uses-feature。但,如果Nfc并不是app的主要功能,不建议在清单文件中配置。
<uses-feature android:name="android.hardware.nfc" android:required="true" />如果没有配置<uses-feature>可能导致不支持nfc功能的android设备安装上了该应用。可以使用如下代码进行检测判断
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this); if (adapter == null) Toast.makeText(MainActivity.this, "nfc不支持", Toast.LENGTH_SHORT).show(); if (adapter != null && !adapter.isEnabled()) { Toast.makeText(MainActivity.this, "nfc未打开", Toast.LENGTH_SHORT).show(); }
action的配置
当android设备扫描到有nfc设备时(未锁屏状态下,android设备会不停地扫描nfc设备,除非用户在手机设置中关闭了nfc功能),系统会发送一个intent。因此,为了获取到该intent, 需要在相应的activity配置中加上<intent-filter>。该intent一共有以下三个action:
<action android:name="android.nfc.action.NDEF_DISCOVERED"/><action android:name="android.nfc.action.TECH_DISCOVERED" /><action android:name="android.nfc.action.TAG_DISCOVERED" />
三个action的匹配顺序如下:
NDEF_DISCOVERED
当nfc设备(tag)中存储的数据为ndef格式并且系统可以识别数据的类型(MIME Type或者 URI)时,intent的action为该值。如:匹配纯文本
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /><!--MIME Type--></intent-filter>匹配链接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" /><!--uri--></intent-filter>在上面配置intent-filter时,在<data>标签中指定了数据格式,只有满足该action,并且数据满足格式满足data中指定的这个intent-filter才会通过,才会启动该activity。
TECH_DISCOVERED
如果没有activity处理第一种intent,intent的action便为第二种。如上面的,假如数据格式不匹配,而手机中没有应用能处理action为ndef_discovered时的intent,那么action的intent便会变为tech_discovered。
匹配该种Intent时,必须创建一个xml文件(该xml文件放置在res/xml文件夹中)用来指定当前activity所支持的nfc技术,这些技术名称写在tech-list集合中。在清单文件中,通过meta-data将这份xml引入。其中常用的技术及tech-list格式如下:
<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说明
文档原文如下:Your activity is considered a match if a tech-list set is a subset of the technologies that are supported by the tag, which you can obtain by calling getTechList().You can also specify multiple tech-list sets. Each of the tech-list sets is considered independently, and your activity is considered a match if any single tech-list set is a subset of the technologies that are returned by getTechList().一份xml文件中可以有多个<tech-list>,每一个<tech-list>可以指定多个<tech>标签。假设设备支持的tech为集合A,只要有一个<tech-list>为集合A的子集,那么第二个intent便会匹配成功。否则不会。
如北京一卡通的tech为:android.nfc.tech.IsoDep与android.nfc.tech.NfcA。那么xml如下的话:
<tech-list><tech>android.nfc.tech.IsoDep</tech></tech-list><tech-list><tech>android.nfc.tech.NfcV</tech></tech-list><tech-list><tech>android.nfc.tech.NfcF</tech></tech-list>该intent便会匹配成功。将第一个<tech-list>换成
<tech-list><tech>android.nfc.tech.IsoDep</tech><tech>android.nfc.tech.NfcA</tech></tech-list>也会匹配成功。但如果将第一个换成:
<tech-list><tech>android.nfc.tech.IsoDep</tech><tech>android.nfc.tech.NfcB</tech></tech-list>那么第二个intent便不会匹配成功,因为NfcB并不在设备支持的集合中,所以该xml文件中没有一个<tech-list>是一卡通支持的子集。
示例
其中的nfc_tech_filter便是上面的<tech-list>所在的xml文件。
<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>
TAG_DISCOVERED
如果经过前两种仍没有找到activity匹配上,那么intent的action便会降为tag_discovered。配置如下:<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/></intent-filter>但通过该action匹配上的可能很少,并且即使匹配上了,在处理nfc设备中的数据时也不方便。所以,不建议配置该filter。
获取数据
当该activity是因为nfc的intent被启动时, 可以从intent中获取这个设备的信息。intent含有如下的extra信息:1,EXTRA_TAG(必需的):一个代表着当前设备的Tag对象。
2,EXTRA_NDEF_MESSAGES(可选的):从设备中解析的一系列的NDEF message。当intent的action为ACTION_NDEF_DISCOVERED,该extra便是必需的,一定有的。
3,EXTRA_ID(可选的):设备的id(low_level id)。
ndef格式
当action为ndef_discovered时,系统会自动将nfc设备所存储的信息封装成NdefMessage对象,而一个NdefMessage中含有若干个NdefRecord对象。获取代码如下:
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {//判断是不是ndef_discovered NdefMessage[] extra = (NdefMessage[]) getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefRecord[] records = extra[0].getRecords(); Log.e(TAG, "读取到有数据:"+new String(records[0].getPayload()));虽然说获取到的NdefMessage数组大部分时候只有一个元素,但为了兼容以后的发展,故这里将NdefMessage数组封装到intent中了。
由于一个message在可能含有多个record对象,所以nfc设备中的数据信息并不单单存储到第一个record中。
其余
第一步,获取tag对象:
Tag extra = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);第二步:根据nfc设备支持的技术,将tag转换成相应的对象。如一卡通支持android.nfc.tech.IsoDep,转换如下:
IsoDep dep = IsoDep.get(extra);
这些类都在android.nfc.tech包中。而且所有的都是通过静态方法get()获取相应的对象。
NdefRecord
NdefRecord应该包含如下信息:
1,3-bit的tnf(Type Name Format):用于表明该如何解析可变长度的type字段。
2,可变长度的type:描述该条record的type。
3,可变长度的id:当前record的id。这个字段用的不多,但如果你需要当前tag的唯一标识,可以通过这个id进行创造。
4,可变长度的负载(payload):程序需要读写的真实数据。由于一个message可以包含多个record,所以全部的负载并不仅仅包含在第一个record中。
示例
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this); if (adapter == null) Toast.makeText(MainActivity.this, "nfc不支持", Toast.LENGTH_SHORT).show(); if (adapter != null && !adapter.isEnabled()) { Toast.makeText(MainActivity.this, "nfc未打开", Toast.LENGTH_SHORT).show(); } onNewIntent(getIntent()); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { NdefMessage[] extra = (NdefMessage[]) intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefRecord[] records = extra[0].getRecords(); Log.e(TAG, "读取到有数据:" + new String(records[0].getPayload())); } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) { Tag extra = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); //android.nfc.tech.IsoDep android.nfc.tech.NfcA String[] list = extra.getTechList(); for (String tech : list) { Log.e(TAG, tech);//输出当前nfc设备支持的tech } final IsoDep dep = IsoDep.get(extra); if (dep != null) { Toast.makeText(MainActivity.this, "iso dep", Toast.LENGTH_SHORT).show(); } } }其清单文件intent-filter为:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <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" />其中的nfc_tech_filter如下:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><tech-list><tech>android.nfc.tech.IsoDep</tech></tech-list><tech-list><tech>android.nfc.tech.NfcV</tech></tech-list><tech-list><tech>android.nfc.tech.NfcF</tech></tech-list></resources>
- nfc入门
- Android NFC编程入门
- NFC开发入门篇
- NFC
- nfc
- NFC
- nfc
- NFC
- nfc
- NFC
- NFC
- nfc
- NFC
- NFC
- NFC
- NFC
- NFC
- NFC
- android 输入框EditText禁止输入Emoji表情符
- yii的csrf验证
- 在开始性能测试之前,我们需要知道什么?
- stm8 调试硬件I2C心得http://bbs.21ic.com/icview-688762-1-1.html
- 修改PLSQL字符编码
- nfc入门
- 免费的Git私有代码托管服务
- kettle工具导出excel报错内存溢出的解决方法GC overhead limit exceeded
- mongo3安装配置系统服务
- AFNetworking 网络请求
- 计算机冷知识
- opentld 出错解决方案
- cpufreq 五种模式
- Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法