android智能终端SDK

移动支付产品接入文档


NFC功能

<h4>前言</h4> <p>Near Field Communication (NFC) 又称近距离无线通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输,在十厘米(3.9英寸)内交换数据。 &amp; 官方文档:<a href="https://developer.android.com/guide/topics/connectivity/nfc">https://developer.android.com/guide/topics/connectivity/nfc</a></p> <p><strong>完整的Demo</strong> <a href="https://github.com/fangmd/NFC_Demo">https://github.com/fangmd/NFC_Demo</a> [<a href="http://www.szzkc.com/down_data_list_240.html](http://112.74.26.209:8099/down_data_list_240.html">http://www.szzkc.com/down_data_list_240.html](http://112.74.26.209:8099/down_data_list_240.html</a> &quot;完整的Demo&quot;)</p> <p>CPU卡读写DEMO [ttp://www.szzkc.com/down_data_list_268.html](<a href="http://112.74.26.209:8099/down_data_list_268.html">http://112.74.26.209:8099/down_data_list_268.html</a> &quot;CPU卡读写DEMO&quot;) [](<a href="http://www.szzkc.com/down_data_list_268.html">http://www.szzkc.com/down_data_list_268.html</a> &quot;CPU卡读写DEMO&quot;)</p> <p><strong>参考:</strong> <a href="https://zh.wikipedia.org/wiki/%E8%BF%91%E5%A0%B4%E9%80%9A%E8%A8%8A">https://zh.wikipedia.org/wiki/%E8%BF%91%E5%A0%B4%E9%80%9A%E8%A8%8A</a> <a href="https://developer.android.com/guide/topics/connectivity/nfc/nfc.html">https://developer.android.com/guide/topics/connectivity/nfc/nfc.html</a> <a href="http://www.jianshu.com/p/a3a3b3db6b37">http://www.jianshu.com/p/a3a3b3db6b37</a> <a href="http://blog.csdn.net/menghnhhuan/article/details/16947361">http://blog.csdn.net/menghnhhuan/article/details/16947361</a> <a href="http://blog.csdn.net/menghnhhuan/article/details/16947361">http://blog.csdn.net/menghnhhuan/article/details/16947361</a></p> <h4>NFC 的三种工作模式</h4> <p><strong>卡模拟模式(Card emulation mode):</strong>将设备模拟成采用RFID技术的IC卡。进行卡模拟的设备必须自带安全组件(Security Element, SE),NFC芯片。 <strong>点对点模式(P2P mode):</strong>和红外线,蓝牙类似用于数据交换。在Android Beam之后android系统支持了点对点数据传输。 <strong>读卡器模式(Reader/Writer mode):</strong>作为非接触读卡器使用,比如从海报或者展览信息电子标签上读取相关信息。</p> <h4>Android 系统检测NFC流程</h4> <ol> <li>Android设备在开启NFC功能后无论屏幕是否打开都会一直监听设备附近的 NFC tag;</li> <li>到 NFC tag 后会解析内部附带的数据:MIME/URI (不同类型的NFC tag 所携带的数据也不一样);</li> <li>将解析到的数据存到intent中,通过intent开启应用;</li> </ol> <h4>intent 类型</h4> <p>下面的排序按优先级从高到低。</p> <p>1、TION_NDEF_DISCOVERED :当tag中附带NDEF数据的时候 2、TION_TECH_DISCOVERED :当tag中没有检测到NDEF数据,但是其中包含的数据是已知的类型 3、TION_TAG_DISCOVERED :如果上面两种都没有检测到,就使用这个启动应用</p> <p><img src="http://doc.szzkc.com/Public/Uploads/2019-05-05/5cce5be680aab.png" alt="" /> <img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=23c6f63f072c489bc79969467e226bb0&amp;amp;file=file.png" alt="" /></p> <h4>NFC 基本使用</h4> <p><strong>申请权限 AndroidManifest.xml</strong></p> <pre><code class="language-java">&amp;lt;uses-permission android:name=&amp;quot;android.permission.NFC&amp;quot; /&amp;amp;</code></pre> <p>申明app具有nfc功能 (非必须) 下面标签作用:在应用商店显示本app需要手机支持NFC功能,如果 NFC功能是非必须的,可以不声明,在代码中通过 getDefaultAdapter() 的返回值判断手机是否支持NFC。</p> <pre><code class="language-java">&amp;lt;uses-feature android:name=&amp;quot;android.hardware.nfc&amp;quot; android:required=&amp;quot;true&amp;quot; /&amp;amp;</code></pre> <p><strong>Filter 设置</strong> 例子1:MIME:</p> <pre><code class="language-java">&amp;lt;intent-filter&amp;amp; &amp;lt;action android:name=&amp;quot;android.nfc.action.NDEF_DISCOVERED&amp;quot;/&amp;amp; &amp;lt;category android:name=&amp;quot;android.intent.category.DEFAULT&amp;quot;/&amp;amp; &amp;lt;data android:mimeType=&amp;quot;text/plain&amp;quot; /&amp;amp; &amp;lt;/intent-filter&amp;amp;</code></pre> <p><strong>例子2:URI:</strong> <a href="http://developer.android.com/index.html">http://developer.android.com/index.html</a>.</p> <pre><code class="language-java">&amp;lt;intent-filter&amp;amp; &amp;lt;action android:name=&amp;quot;android.nfc.action.NDEF_DISCOVERED&amp;quot;/&amp;amp; &amp;lt;category android:name=&amp;quot;android.intent.category.DEFAULT&amp;quot;/&amp;amp; &amp;lt;data android:scheme=&amp;quot;http&amp;quot; android:host=&amp;quot;developer.android.com&amp;quot; android:pathPrefix=&amp;quot;/index.html&amp;quot; /&amp;amp; &amp;lt;/intent-filter&amp;amp;</code></pre> <h4>ACTION_TECH_DISCOVERED</h4> <p>如果定义了这个action,必须创建一个XML资源文件定义activity所支持的协议 res/xml 文件夹下创建资源文件:(例子)</p> <pre><code class="language-java">&amp;lt;resources xmlns:xliff=&amp;quot;urn:oasis:names:tc:xliff:document:1.2&amp;quot;&amp;amp; &amp;lt;tech-list&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.IsoDep&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.NfcA&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.NfcB&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.NfcF&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.NfcV&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.Ndef&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.NdefFormatable&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.MifareClassic&amp;lt;/tech&amp;amp; &amp;lt;tech&amp;amp;android.nfc.tech.MifareUltralight&amp;lt;/tech&amp;amp; &amp;lt;/tech-list&amp;amp; &amp;lt;/resources&amp;amp;</code></pre> <p>在 AndroidManifest.xml 中创建</p> <pre><code class="language-java">&amp;lt;activity&amp;amp; &amp;lt;intent-filter&amp;amp; &amp;lt;action android:name=&amp;quot;android.nfc.action.TECH_DISCOVERED&amp;quot;/&amp;amp; &amp;lt;/intent-filter&amp;amp; &amp;lt;meta-data android:name=&amp;quot;android.nfc.action.TECH_DISCOVERED&amp;quot; android:resource=&amp;quot;@xml/nfc_tech_filter&amp;quot; /&amp;amp; &amp;lt;/activity&amp;amp;</code></pre> <h4>ACTION_TAG_DISCOVERED</h4> <pre><code class="language-java">&amp;lt;intent-filter&amp;amp; &amp;lt;action android:name=&amp;quot;android.nfc.action.TAG_DISCOVERED&amp;quot;/&amp;amp; &amp;lt;/intent-filter&amp;amp;</code></pre> <p>从Intent中获取数据intent中可能携带的数据有下面三种,具体哪个里面有数据取决于检测到的NFC tag中的数据类型</p> <p>1、TRA_TAG :必须 2、TRA_NDEF_MESSAGES :可选 3、TRA_ID :可选</p> <p>获取数据的例子:</p> <pre><code class="language-java">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 &amp;lt; rawMsgs.length; i++) { msgs[i] = (NdefMessage) rawMsgs[i]; } } } //process the msgs array } </code></pre> <p>或者:可以从Intent中获取Tag对象,tag对象中包含了数据和数据类型</p> <pre><code class="language-java">Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);</code></pre> <h4>处理 Tag 对象</h4> <p>获取tag对应的技术标准对象:</p> <p>技术标准有: &amp; IsoDep MifareClassic MifareUltralight Ndef NdefFormatable NfcA NfcB NfcBarcode NfcF NfcV</p> <h4>MifareClassic格式标签读写</h4> <p>MifareClassic格式标签数据结构 <img src="http://doc.szzkc.com/Public/Uploads/2019-05-05/5cce5ec6a4836.png" alt="" /> <img src="http://doc.szzkc.com/Public/Uploads/2019-05-05/5cce5ecebb605.png" alt="" /> <img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=c8e3adec23f35205f05cce96f810aee0&amp;amp;file=file.png" alt="" /> <img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=c02999901483cbcffd718171803c5cee&amp;amp;file=file.png" alt="" /></p> <p>第一扇区的第一块一般用于制造商占用块</p> <p>0-15个扇区:一个扇区对应4个块,所以总共有64个块,序号分别为0-63,第一个扇区对应:0-3块,第二个扇区对应:4-7块…</p> <p>每个扇区的最后一个块用来存放密码或控制位,其余为数据块,一个块占用16个字节,keyA占用6字节,控制位占用4字节,keyB占用6字节。</p> <p>MifareClassic标签读写常用api:</p> <p>get():根据Tag对象来获得MifareClassic对象; Connect():允许对MifareClassic标签进行IO操作; getType():获得MifareClassic标签的具体类型:TYPE_CLASSIC,TYPE_PLUA,TYPE_PRO,TYPE_UNKNOWN; getSectorCount():获得标签总共有的扇区数量; getBlockCount():获得标签总共有的的块数量; getSize():获得标签的容量:SIZE_1K,SIZE_2K,SIZE_4K,SIZE_MINI authenticateSectorWithKeyA(int SectorIndex,byte[] Key):验证当前扇区的KeyA密码,返回值为ture或false。 常用KeyA:默认出厂密码:KEY_DEFAULT,各种用途的供货商必须配合该技术的MAD:KEY_MIFARE_APPLICATION_DIRECTORY 被格式化成NDEF格式的密码:KEY_NFC_FORUM getBlockCountInSector(int):获得当前扇区的所包含块的数量; sectorToBlock(int):当前扇区的第1块的块号; writeBlock(int,data):将数据data写入当前块;注意:data必须刚好是16Byte,末尾不能用0填充,应该用空格 readBlock(int):读取当前块的数据。 close():禁止对标签的IO操作,释放资源。</p> <p>例子:</p> <pre><code class="language-java">IsoDep isoDep = IsoDep.get(tag);</code></pre> <p>获取到该对象后进行I/O流读写,注意读写代码属于耗时操作需要在子线程中执行</p> <p>要从nfc卡中读取信息,需要发起一个指令才能收到相应的信息,不同的nfc卡的指令不同。</p>

页面列表

ITEM_HTML