Android NFC开发MifareUltralight读写Demo实例下载
简介
基于这两天一直在研究NFC的相关技术、昨天发表了一篇 Android NFC开发MifareClassic读写Demo实例下载 相关的文章、是Android NFC的MifareClassic数据格式的实现方式、今天将和大家分享另外一种数据格式的读写方式MifareUltralight、希望有需求的哥们少走弯路
Tag技术支持工作
当使NFC Tag和Android的供电设备生效、使用Tag来读取和写入数据的主要格式是NDEF、当设备扫描NDEF数据的Tag、Android提供支持解析的消息、并在可能的情况下将它传入一个NdefMessage、但是、在有些情况下、当你扫描不包含NDEF数据的Tag或当NDEF数据时无法映射到MIME类型或URI时、在那样的情况下、你需要直接与Tag建立沟通及用自己的协议(在原始字节)读写它、Android用android.nfc.tech包对那些情况提供了通用的支持、如表1中所描述的、您可以使用getTechList()方法来确定技术支持Tag、并且用由android.nfc.tech提供的类的其中一个创建相应TagTechnology对象
支持的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 | 提供对那些被格式化为NDEF的tag的数据的访问和其他操作 |
NdefFormatable | 对那些可以被格式化成NDEF格式的tag提供一个格式化的操作 |
可选的支持的Tag技术
类 | 描述 |
---|---|
MifareClassic | 如果android设备支持MIFARE,提供对MIFARE Classic目标的属性和I/O操作。 |
MifareUltralight | 如果android设备支持MIFARE,提供对MIFAREUltralight目标的属性和I/O操作。 |
Tag技术工作和 ACTION_TECH_DISCOVERED Intent
当一个设备扫描一个有NDEF数据的Tag、但不能被映射到一个MIME或URI时、Tag发布系统试图启动一个Activity与ACTION_TECH_DISCOVERED Intent、当非NDEF被扫描到时、ACTION_TECH_DISCOVERED的Tag也可以使用.如果Tag发布系统无法为你解析它、此回退让你直接进行扫描标签上的数据、基本步骤与标签技术如下
过滤一个你想要处理的Tag技术的 ACTION_TECH_DISCOVERED intent. 获取更多信息请参阅 过滤 NFC intents. 一般来说、当一个NDEF消息不能被映射到MIME类型或者URI上时、Tag发布系统尝试启动一个ACTION_TECH_DISCOVERED intent、否则如果被扫描到的Tag不包含NDEF数据. 欲了解如何确定的更多信息、请参阅Tag发布系统
当你的应用程序接收到该Intent、从以图中获取Tag对象
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
通过调用在android.nfc.tech包的类中的一个get factory方法、获取到TagTechnology的一个实例 . 你可以在调用一个get factory方法以前、计算支持Tag技术通过调用getTechList()、举例来说、为了从一个Tag得到MifareUltralight的一个实例、请执行下列操作
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
读取和写入Tags
读取和写入NFC tag涉及到从Intent中获取到Tag并创建与tag的连接、你必须定义你自己的协议来读写数据到Tag、然后、记住当直接使用Tag时你仍然能够读写NDEF数据、你想要如何构建东西、它可以实现、如下的例子演示如何使用一个MIFARE Ultralight tag
读取数据
public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload1 = mifare.readPages(4); byte[] payload2 = mifare.readPages(8); return new String(payload1, Charset.forName("US-ASCII")) new String(payload2, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight message...", e); return "读取失败!"; } catch (Exception ee) { Log.e(TAG, "Exception message...", ee); return "读取失败!"; } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } }
写数据
public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "aaaa".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "bbbb".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "cccc".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "dddd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(8, "eeee".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(9, "ffff".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(10, "gggg".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(11, "hhhh".getBytes(Charset.forName("US-ASCII"))); Toast.makeText(this, "成功写入", Toast.LENGTH_SHORT).show(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "Exception MifareUltralight...", e); } } }
使用前端发布系统
前端发布系统允许一个activity拦截一个 intent并且要求由于其他处理同样intent的activities、使用这个系统涉及到为了Android系统能够发送合适的intents给你的应用程序而构建几个数据结构、为了使前端发布系统有效
首先、创建一个 PendingIntent 对象、以便系统可以在它被扫描到时、用tag的细节填充它、然后、在Intent filters里声明你想要处理的Intent、一个tag被检测到时先检查前台发布系统、如果前台Activity符合Intent filter的要求、那么前台的Activity的将处理此Intent、如果不符合、前台发布系统将Intent转到Intent发布系统、如果指定了null的Intent filters、当任意tag被检测到时、你将收到TAG_DISCOVERED intent、下面的代码片断处理所有NDEF_DISCOVERED的MIME类型、因此请注意你应该只处理你想要的Intent、最后、设置一个你程序要处理的Tag technologies的列表、调用Object.class.getName() 方法来获得你想要支持处理的technology类
onCreate代码如下
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); promt = (TextView) findViewById(R.id.text); writeButton = (Button)findViewById(R.id.writeTag_button); writeButton.setOnClickListener(this); // 获取默认的NFC控制器 mAdapter = NfcAdapter.getDefaultAdapter(this); if (mAdapter == null) { promt.setText("设备不支持NFC!"); Toast.makeText(this, "设备不支持NFC!", Toast.LENGTH_SHORT).show(); finish(); return; } if (!mAdapter.isEnabled()) { promt.setText("请在系统设置中先启用NFC功能!"); Toast.makeText(this, "请在系统设置中先启用NFC功能!", Toast.LENGTH_SHORT).show(); finish(); return; } pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()) .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter ndef = new IntentFilter(NfcAdapter .ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, }; techListsArray = new String[][] { new String[] { MifareUltralight.class.getName() } }; }
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 }
好了、到这里、基本的核心代码就分析完了、希望对大家有用、另外关于AndroidManifest.xml和nfc_teach_filter.xml请参考另外一篇文章 Android NFC开发MifareClassic读写Demo实例下载
Android官方MifareUltralight文档请参考http://developer.android.com/intl/zh-cn/reference/android/nfc/tech/MifareUltralight.html
国内是无法访问 developer.android.com 的、另如果想访问 developer.android.com 可参考 国内如何*访问google.com_google.hk
源代码下载链接: http://dwtedx.com/download.html?bdkey=s/1gdGSuUB 密码: sip7