摘要:終于,在去年的上,蘋(píng)果宣布開(kāi)放其接口,這為以后的應(yīng)用開(kāi)發(fā)提供了更多的可能。目前,蘋(píng)果的對(duì)的格式支持有限,暫時(shí)僅支持格式。
前言
NFC這個(gè)詞相信大家現(xiàn)在都已經(jīng)不陌生了,各大城市的地鐵、商場(chǎng)等等支持NFC支付一度成為頭條的熱點(diǎn)。其實(shí)很早之前就已經(jīng)有二維碼和NFC的誕生了,但是由于二維碼成本低廉,技術(shù)門(mén)檻相對(duì)較低,因此,二維碼迅速搶占了移動(dòng)支付的市場(chǎng),但是,與此同時(shí)NFC的發(fā)展并未因此停止。
其實(shí)在安卓端的NFC發(fā)展已經(jīng)非常迅猛了,只是我們的蘋(píng)果爸爸遲遲不肯帶我們一起玩NFC。終于,在去年的WWDC上,蘋(píng)果宣布“開(kāi)放”其N(xiāo)FC接口,這為以后NFC的應(yīng)用開(kāi)發(fā)提供了更多的可能。
關(guān)于NFC
NFC(Near Field Communication)近場(chǎng)通信,當(dāng)兩個(gè)設(shè)備相互靠近時(shí)能進(jìn)行信息交流的一個(gè)技術(shù)。
使用了NFC技術(shù)的設(shè)備(比如手機(jī))可以在彼此靠近的情況下進(jìn)行數(shù)據(jù)交換,是由非接觸式射頻識(shí)別(RFID)及互連互通技術(shù)整合演變而來(lái),通過(guò)在單一芯片上集成感應(yīng)式讀卡器、感應(yīng)式卡片和點(diǎn)對(duì)點(diǎn)通信的功能,利用移動(dòng)終端實(shí)現(xiàn)移動(dòng)支付、電子票務(wù)、門(mén)禁、移動(dòng)身份識(shí)別、防偽等應(yīng)用。目前,蘋(píng)果的CoreNFC對(duì)NFC的格式支持有限,暫時(shí)僅支持NDEF格式。
關(guān)于NDEF
NDEF(NFC Data Exchange Format)是一種能夠在NFC設(shè)備或者標(biāo)簽之間進(jìn)行信息交換的數(shù)據(jù)格式。NDEF格式由各種 NDEF Messages 和 NDEF Records 組成。NDEF格式使用了一種容易理解的格式來(lái)存儲(chǔ)和交換信息,如:URI、純文本等等。
NFC標(biāo)簽,像Mifare Classic卡片可以配置為NDEF標(biāo)簽,通過(guò)一個(gè)NFC設(shè)備寫(xiě)入的數(shù)據(jù)可以被其他NDEF兼容的設(shè)備訪問(wèn)。NDEF消息還可以用于兩個(gè)活躍的NFC設(shè)備之間“點(diǎn)對(duì)點(diǎn)”模式交換數(shù)據(jù)。
NDEF Messages
NDEF Messages是NDEF Records交換機(jī)制的基礎(chǔ),每一個(gè)message包含一個(gè)或多個(gè)records。
NDEF Records
NDEF Records包含一個(gè)特定的payload,并且有以下結(jié)構(gòu)來(lái)標(biāo)識(shí)內(nèi)容和記錄大小:
Record Header(記錄頭)
記錄頭包含了很多重要的信息,它占用3個(gè)位來(lái)標(biāo)識(shí)遵循TNF協(xié)議的記錄的類(lèi)型,講人話(huà)就是這3個(gè)位用來(lái)表示這條記錄的類(lèi)型的。
TNF: Type Name Format 字段
一條NDEF記錄的類(lèi)型名稱(chēng)是一個(gè)3個(gè)位的數(shù)值,用來(lái)描述這條記錄的類(lèi)型,并且可以用來(lái)設(shè)置對(duì)該記錄中其它的結(jié)構(gòu)和內(nèi)容的期望。簡(jiǎn)單的說(shuō)就是這3個(gè)位不僅可以表示該條記錄的類(lèi)型,也可以在一定程度上決定了該條記錄接下來(lái)的數(shù)據(jù)結(jié)構(gòu)??赡艿挠涗浢Q(chēng)如下表:
TNF Value
Record Type
0x00
Empty Record 表明這條記錄沒(méi)有類(lèi)型、id或有效payload。這個(gè)記錄類(lèi)型一般用于新格式化的NDEF卡上,因?yàn)镹DEF標(biāo)簽必須有至少一個(gè)NDEF紀(jì)錄。
0x01
Well-Known Record 表明記錄類(lèi)型字段使用RTD類(lèi)型名稱(chēng)格式。這種類(lèi)型名稱(chēng)用一個(gè)Record Type Definition (RTD)來(lái)存儲(chǔ)任何指定的類(lèi)型,例如:存儲(chǔ)RTD文本、RTD URIs等等。同時(shí),這是一種比較常用的也比較有用的記錄類(lèi)型。
0x02
MIME Media Record 表明payload是這條NDEF記錄分塊的中間或者最后一塊。
0x03
Absolute URI Record 表明這條記錄的類(lèi)型字段一定包含一個(gè)URI字段。
0x04
External Record 表明這條記錄的類(lèi)型字段包含一個(gè)RTD格式的外部字段。
0x05
Unknown Record 表明payload的類(lèi)型未知。
0x06
Unchanged Record 未發(fā)生變化的記錄類(lèi)型,釋同MIME Media Record。
IL:ID Length 字段
IL是ID長(zhǎng)度的標(biāo)志位,用來(lái)表示下面的ID Length字段是否省略。如果這個(gè)位設(shè)置為0,則該條記錄中省略ID Length。
SR:Short Record 位
短記錄標(biāo)志位,如果下面的PAYLOAD LENGTH字段小于等于一個(gè)字節(jié),則該位設(shè)置為1 。
CF:Chunk Flag
塊標(biāo)識(shí)位,用于標(biāo)識(shí)當(dāng)前塊是第一個(gè)記錄塊還是中間的記錄塊。
ME:Message End
結(jié)束標(biāo)志位,用于標(biāo)識(shí)當(dāng)前記錄是否是當(dāng)前Message的最后一條記錄。
MB:Message Begin
起始標(biāo)志位,用于標(biāo)識(shí)當(dāng)前記錄是否是當(dāng)前Message的第一條記錄。
Type Length
表示類(lèi)型字段的長(zhǎng)度。對(duì)于上面TNF字段描述中的某些值,該字段一直為0 。
Payload Length
表示該條記錄的payload字段長(zhǎng)度。如果上面的SR字段設(shè)置為1,則該字段占用1個(gè)字節(jié)的長(zhǎng)度,但是如果SR設(shè)置為0,則該字段將有32個(gè)位,占用4個(gè)字節(jié)的長(zhǎng)度。
ID Length
表示該條記錄的ID的長(zhǎng)度。只有當(dāng)上面的IL位置1時(shí)該字段才會(huì)被省略。
Record Type
表示記錄的類(lèi)型,這個(gè)字段的值必須根據(jù)TNF位的設(shè)置確定。
Record ID
表示該條記錄的ID。當(dāng)IL位為0時(shí),該字段省略。
Payload
表示該條記錄的payload,該字段的長(zhǎng)度務(wù)必與上面的Payload Length字段值一致。
關(guān)于 Well-Known Records 和 URI Records
首先要說(shuō)的就是這兩個(gè)概念的區(qū)別,Well-Known Records(TNF Record Type 0x01) 是最常用也是最有用的NFC記錄類(lèi)型,它是寫(xiě)在上面說(shuō)到的TNF字段的三個(gè)位里的,它描述的是當(dāng)前這條NDEF記錄的整體類(lèi)型,相當(dāng)于一個(gè)總的架構(gòu)決策。
而 URI Records(0x55/‘U’)是比較有用的數(shù)據(jù)類(lèi)型,它是寫(xiě)在上面 Recode Type 字段的一個(gè)字節(jié)(8個(gè)位)里的,它描述的是這條NDEF記錄攜帶的數(shù)據(jù)信息類(lèi)型,簡(jiǎn)單的說(shuō)就是這條記錄攜帶了什么樣的信息。
這里,關(guān)于這個(gè)URI Records我要多說(shuō)幾句,這個(gè)類(lèi)型可以用來(lái)存儲(chǔ)例如電話(huà)號(hào)碼、網(wǎng)站地址以及各種協(xié)議的鏈接等等很多有用的信息,它的結(jié)構(gòu)定義如下:
第一個(gè)字節(jié)表示該類(lèi)型的識(shí)別碼,這個(gè)識(shí)別碼的主要是用于縮短URI的長(zhǎng)度,它的有效值詳見(jiàn)下表:
后面的N個(gè)字節(jié)就是用來(lái)表示一個(gè)URI去掉前面識(shí)別碼之后剩余的部分,舉個(gè)例子:例如我們要將 https://www.mob.com 寫(xiě)入,則在第一個(gè)字節(jié)里我們要寫(xiě)入的是 0x02,表示 https://www.,接下來(lái)要連續(xù)寫(xiě)入的就是 0x6D 0x6F 0x62 0x2E 0x63 0x6F 0x6D (詳細(xì)請(qǐng)參考:ASCII碼對(duì)照表http://ascii.911cha.com/)
以上所有內(nèi)容就是關(guān)于NDEF數(shù)據(jù)格式的詳細(xì)說(shuō)明了,那么這里也很不幸的告訴大家,我們平時(shí)直接從某寶、某東或者某某某上買(mǎi)來(lái)的NFC卡片(俗稱(chēng):白卡)都不會(huì)是NDEF格式的,所以。。。
將 Mifare Classic Cards 用作 NDEF 標(biāo)簽
Mifare Classic 1K和4K的卡可以被初始化為NFC的NDEF格式標(biāo)簽。關(guān)于Mifare的詳細(xì)介紹請(qǐng)各位老板參見(jiàn):Mifare維基百科 Mifare Classic 可以配置為NFC論壇兼容的NDEF標(biāo)簽,但必須以某種特定的方式組織它里面的數(shù)據(jù)才可以。具體要求可以參考如下資料:
AN1304 - NFC Type MIFARE Classic Tag Operation
https://www.nxp.com/docs/en/application-note/AN1304.pdf
上面的是使用手冊(cè)的權(quán)威來(lái)源,下面將快速的介紹一下將 Mifare Classic Cards 用作 NDEF 標(biāo)簽所涉及的關(guān)鍵概念。
1. Mifare Application Directory (MAD)
Mifare應(yīng)用程序的目錄,為了在Mifare Classic卡片的扇區(qū)內(nèi)存與單個(gè)NDEF記錄之間建立關(guān)系而存在。MAD表明了哪個(gè)扇區(qū)包含著哪個(gè)NDEF記錄。關(guān)于Mifare應(yīng)用程序目錄的權(quán)威信息來(lái)源如下:
AN10787 - MIFARE Application Directory (MAD)
https://www.nxp.com/docs/en/application-note/AN10787.pdf
為了兼容性考慮,官方根據(jù)卡片內(nèi)存的大小定義了兩種不同類(lèi)型的MAD,簡(jiǎn)單說(shuō)明一下區(qū)別,MAD1可以用在任何卡片上,而MAD2只能用在內(nèi)存大于1K字節(jié)的卡片上。
2. 存儲(chǔ) NDEF Messages
為了在Mifare Classic卡上存儲(chǔ)NDEF消息,消息需要被封裝在一個(gè)叫做 TLV 塊 的東西里面。關(guān)于 TLV 塊 的基本結(jié)構(gòu)描述如下:
TLV 是三個(gè)不同維度的縮寫(xiě):T:Tag Field 標(biāo)簽L:Length Field 長(zhǎng)度V:Value Field 數(shù)值
一個(gè) TLV 塊 由一個(gè)或多個(gè)字節(jié)組成,這取決于上面三個(gè)維度的存在情況,但至少有一個(gè)字節(jié),因?yàn)?T 字段在每種情況下都是強(qiáng)制性的。
Tag Field
標(biāo)簽字段是唯一必填的字段,使用單個(gè)字節(jié)來(lái)標(biāo)識(shí) TLV 塊 的類(lèi)型,有效值如下:
Length Field
長(zhǎng)度字段包含了數(shù)值字段的長(zhǎng)度(字節(jié)),它可以使用一個(gè)或三個(gè)字節(jié)兩種不同的方式表示:一個(gè)字節(jié)格式就是簡(jiǎn)單0x00~0xFF的一個(gè)字節(jié)數(shù)值;三個(gè)字節(jié)格式的組成如下:
Value Field
數(shù)值字段僅在長(zhǎng)度字段存在且不等于0x00時(shí)才存在,這個(gè)字段就是 payload 的存儲(chǔ)位置。
Terminator TLV
終止符,是數(shù)據(jù)區(qū)域中的最后一個(gè)TLV 塊,固定的單個(gè)字節(jié):0xFE,這個(gè)TLV 塊也是是強(qiáng)制性的。
3. 一個(gè)帶有NDEF記錄的Mifare Classic 卡片的內(nèi)存示例
上圖示例中在扇區(qū)1包含了兩個(gè)NDEF記錄:
第一個(gè)記錄在扇區(qū)1塊4的前兩個(gè)字節(jié):根據(jù)上面的描述,每個(gè)記錄都以TLV 塊開(kāi)頭,并且TLV 塊的第一個(gè)字節(jié)(值0x00)指示這是一個(gè)空塊類(lèi)型,第二個(gè)字節(jié)是長(zhǎng)度字段,并且也是0x00,因此該記錄沒(méi)有payload,TLV 塊的值字段不存在。當(dāng)Mifare Classic卡首次格式化以確保至少有一條記錄存在時(shí),一般會(huì)插入此記錄。
第二個(gè)記錄從扇區(qū)1塊4的第3個(gè)字節(jié)開(kāi)始,到塊5的第6個(gè)字節(jié)結(jié)束:
同樣,對(duì)于前兩個(gè)字節(jié),根據(jù)TLV 塊的描述,第一個(gè)字節(jié) 0x03 表示這是一個(gè)NDEF Message類(lèi)型,第二個(gè)字節(jié) 0x11 表示該塊的數(shù)據(jù)長(zhǎng)度是17個(gè)字節(jié)。對(duì)于接下來(lái)17個(gè)字節(jié)的分析如下表:
Byte(s)
Value
Description
04:04
0xD1
NDEF記錄的記錄頭,詳細(xì)解釋參考上面的NDEF記錄描述部分。位分配如下:
TNF = 0x01 表示這是一個(gè)Well-Known類(lèi)型的記錄
IL = 0 表示沒(méi)有ID字段
SR = 1 表示這是一個(gè)短記錄
CF = 0 表示這個(gè)塊不是第一塊
ME = 1 表示當(dāng)前記錄為最后一條記錄
MB = 1 表示Message的開(kāi)始
04:05
0x01
NDEF記錄類(lèi)型的長(zhǎng)度,1個(gè)字節(jié),因?yàn)橄旅娴挠涗涱?lèi)型值是0x55
04:06
0x0D
表示payload的長(zhǎng)度,13個(gè)字節(jié)
04:07
0x55
NDEF記錄的類(lèi)型,0x55表示URI類(lèi)型
04:08
0x01
表示payload開(kāi)始,后面的將是payload中的內(nèi)容
04:09..05:04
...
payload內(nèi)容的16進(jìn)制數(shù)據(jù)
最后一個(gè)字節(jié),0xFE 是TLV 塊的終止符,表示這個(gè)塊的結(jié)束,這個(gè)沒(méi)什么好說(shuō)的了~~
相關(guān)參考鏈接:
?NXP官方網(wǎng)站
https://www.nxp.com/
?NFC論壇
https://nfc-forum.org/
?Mifare Classic S50 技術(shù)詳解
http://www.cnblogs.com/SCPlatform/p/5116180.html
iOS CoreNFC
下面將通過(guò)一個(gè)簡(jiǎn)單的示例來(lái)演示怎么使用蘋(píng)果爸爸推出的CoreNFC,該示例僅可以用來(lái)讀取存儲(chǔ)在卡片上的NDEF格式的信息。
為此,我使用了STM32F407單片機(jī)與Adafruit PN532 ShieldNFC讀寫(xiě)模塊配對(duì),將信息寫(xiě)入NDEF格式的卡片上。本文中,我不會(huì)記錄如何將普通的Mifare Classic卡片格式化成NDEF格式的卡片以及如何將數(shù)據(jù)寫(xiě)入到NDEF卡片中(iOS的CoreNFC暫時(shí)不支持寫(xiě)入)。
我們的app要使用NFC必須要進(jìn)行應(yīng)用授權(quán):首先要?jiǎng)?chuàng)建一個(gè)支持NFC的證書(shū),并且開(kāi)啟NFC Tag Reading,如下圖:
導(dǎo)入證書(shū)之后,我們需要進(jìn)行Info.plist配置Privacy - NFC Scan Usage Description權(quán)限,如下圖:
要實(shí)現(xiàn)NFC功能,我們得先導(dǎo)入CoreNFC.framework,并導(dǎo)入其頭文件#import目前為止,iOS模擬器還不支持CoreNFC,只能使用真機(jī)調(diào)試。
與二維碼掃描等類(lèi)似,NFC 也具備一個(gè)用于信息交互的Session,并且這個(gè)Session要在使用期間一直持有,所以初始化Session代碼如下:
@interface NFCTableViewController ()/** NFC Session */@property (nonatomic, strong) NFCNDEFReaderSession *nfcSession;/** founded NFC Messages */@property (nonatomic, strong) NSMutableArray *> *nfcMessages;@end@implementation NFCTableViewController#pragma mark - initializeNFC
- (void)initializeNFCSession { // 創(chuàng)建 Session
self.nfcSession = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_get_main_queue() invalidateAfterFirstRead:NO]; // 設(shè)置 Session 的提示信息
self.nfcSession.alertMessage = @"You can scan NFC-tags by holding them behind the top of your iPhone.";
}@end
經(jīng)過(guò)上面的初始化之后,有了Session就可以開(kāi)啟監(jiān)聽(tīng)了,啟動(dòng)監(jiān)聽(tīng)很簡(jiǎn)單,示例代碼如下:
- (IBAction)startSearchBtnClick:(UIBarButtonItem *)sender { NSLog(@"%s", __func__); // 啟動(dòng)Session
[self.nfcSession beginSession];
}
Session啟動(dòng)時(shí)會(huì)自動(dòng)調(diào)出系統(tǒng)的掃描面板,如下圖:
通過(guò)上面的方式把Session啟動(dòng)之后,設(shè)備就會(huì)自動(dòng)開(kāi)始掃描NDEF格式的標(biāo)簽信息,當(dāng)掃描到標(biāo)簽信息,或者發(fā)生任何異常時(shí)都會(huì)通過(guò)代理方法回調(diào),所以我們需要監(jiān)聽(tīng)Session的回調(diào)信息,示例如下:
#pragma mark - NFCNDEFReaderSessionDelegate/*! * @method readerSession:didInvalidateWithError: * * @param session The session object that is invalidated. * @param error The error indicates the invalidation reason. * * @discussion Gets called when a session becomes invalid. At this point the client is expected to discard * the returned session object. *//** NFC 讀取的session發(fā)生錯(cuò)誤或session過(guò)期時(shí)回調(diào),此時(shí)客戶(hù)端應(yīng)當(dāng)丟棄返回的session,即此session不可重用。 @param session 發(fā)生錯(cuò)誤的session @param error 錯(cuò)誤信息 */- (void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error { if (error)
{ NSLog(@"NFC-Session invalidated: %@", error);
} if (self.nfcSession)
{ // 關(guān)閉當(dāng)前session
[self.nfcSession invalidateSession];
self.nfcSession = nil;
} // 重新初始化一個(gè)新的session
[self initializeNFCSession];
}/*! * @method readerSession:didDetectNDEFs: * * @param session The session object used for tag detection. * @param messages Array of @link NFCNDEFMessage @link/ objects. The order of the discovery on the tag is maintained. * * @discussion Gets called when the reader detects NFC tag(s) with NDEF messages in the polling sequence. Polling * is automatically restarted once the detected tag is removed from the readers read range. *//** 當(dāng)NFC Session在輪詢(xún)隊(duì)列中讀取到NDEF信息時(shí)回調(diào),此時(shí)輪詢(xún)會(huì)自動(dòng)重啟一次再次檢測(cè)NFC標(biāo)簽是否離開(kāi)了讀取范圍。(原理類(lèi)似于機(jī)械按鍵的防抖動(dòng)) @param session 讀取Session @param messages 讀取到的信息 */- (void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray *)messages { NSLog(@"New NFC Messages %zd detected:", messages.count); for (NFCNDEFMessage *message in messages) { NSLog(@"- %zd Records:", message.records.count); for (NFCNDEFPayload *record in message.records) { NSLog(@" - TNF(TypeNameFormat): %@", [self formattedTypeNameFormat:record.typeNameFormat]); NSLog(@" - Payload: %@", [[NSString alloc] initWithData:record.payload encoding:NSUTF8StringEncoding]); NSLog(@" - Type: %@", [[NSString alloc] initWithData:record.type encoding:NSUTF8StringEncoding]); NSLog(@" - Identifier: %@", [[NSString alloc] initWithData:record.identifier encoding:NSUTF8StringEncoding]);
}
}
[self.nfcMessages addObject:messages];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7075.html
摘要:基礎(chǔ)知識(shí)工會(huì)名稱(chēng)項(xiàng)目第個(gè)工作組局域網(wǎng)標(biāo)準(zhǔn)無(wú)線(xiàn)局域網(wǎng)層,物理層技術(shù)規(guī)范開(kāi)放互聯(lián)參考模型的七層架構(gòu)應(yīng)用,表示,會(huì)話(huà),傳輸,網(wǎng)絡(luò),數(shù)據(jù)鏈路,物理數(shù)據(jù)鏈路層邏輯鏈路控制子層媒介訪問(wèn)控制子層只涉及層媒介不同的媒介無(wú)線(xiàn)有線(xiàn)沖突檢測(cè)邊發(fā)送邊監(jiān)聽(tīng)沖突避免 WiFi篇 一。Netd 是守護(hù)進(jìn)程;Netd是Android系統(tǒng)中專(zhuān)門(mén)負(fù)責(zé)網(wǎng)絡(luò)管理和控制的后臺(tái)daemon程序;位于Framework層和Kern...
摘要:移動(dòng)端技術(shù)路線(xiàn)概述在移動(dòng)互聯(lián)網(wǎng)發(fā)展初期,業(yè)務(wù)場(chǎng)景并不復(fù)雜,原生開(kāi)發(fā)還可以應(yīng)對(duì)產(chǎn)品需求迭代。需結(jié)合團(tuán)隊(duì)人員的情況,業(yè)務(wù)場(chǎng)景對(duì)于性能和動(dòng)態(tài)化的需求程度來(lái)考慮哪種技術(shù)方案能帶來(lái)更高的價(jià)值。1. 移動(dòng)端技術(shù)路線(xiàn) 1.1 概述 在移動(dòng)互聯(lián)網(wǎng)發(fā)展初期,業(yè)務(wù)場(chǎng)景并不復(fù)雜,原生開(kāi)發(fā)還可以應(yīng)對(duì)產(chǎn)品需求迭代。 但近幾年,隨著物聯(lián)網(wǎng)時(shí)代到來(lái)、移動(dòng)互聯(lián)網(wǎng)高歌猛進(jìn),日新月異,在很多業(yè)務(wù)場(chǎng)景中,傳統(tǒng)的純?cè)_(kāi)發(fā)已經(jīng)不...
閱讀 845·2023-04-25 19:43
閱讀 4110·2021-11-30 14:52
閱讀 3920·2021-11-30 14:52
閱讀 4024·2021-11-29 11:00
閱讀 3918·2021-11-29 11:00
閱讀 4036·2021-11-29 11:00
閱讀 3752·2021-11-29 11:00
閱讀 6599·2021-11-29 11:00