iOS 11 - 如何 read/parse 来自 CoreNFC 的 NDEF 消息?
iOS 11 - How does one read/parse the NDEF Message from CoreNFC?
我有一堆 URL 标签,内容为“http://WEBSITE.com". Let's say WEBSITE is youtube so http://youtube.com。当我在 Android 等上扫描它们时,它会保留 http 或 https。
我正在尝试使用核心 NFC 框架扫描这些相同的标签。我扫描它们并得到一堆字节,我使用带有 UTF8 编码的 NSSString initWithData 转换这些字节。我回来\^Cyoutube.com。我想得到 http://youtube.com.
我怎样才能拦截有效载荷以获得我需要的东西?如果我假设字符串前面有 http,我怎么知道它是 http 还是 https 甚至是 ftp?
编辑 1:
我在使用以下纯文本记录的答案代码时遇到问题。为 "hello world" 创建文本记录时,我从控制台获得以下输出:
2017-06-09 12:45:35.151806-0400 testNFC[2963:190724] 载荷字符串:https://www.enhello world
2017-06-09 12:45:35.154959-0400 testNFC[2963:190724] 载荷数据:<02656e68 656c6c6f 20776f72 6c64>
获取我使用的字符串
NSString *nfcMessage = [nfcType stringByAppendingString:[[[NSString alloc] initWithData:payload.payload encoding:NSUTF8StringEncoding] substringFromIndex:1]];
nfcType 是您函数中的 return 但对于 None 情况,我 return @"";
我希望得到 hello world。
为此,您首先需要确保您的 NDEF 标签格式正确。您可以使用 Android phone 或 these reader accessories along with an NDEF writing app 之一。
执行以下方法:
- (NSString *)getType:(NSData *)NDEFData {
NSString *firstByte = [self getFirstByte:NDEFData];
if ([firstByte isEqualToString:@"00"]) {
return @"None";
} else if ([firstByte isEqualToString:@"01"]) {
return @"http://www.";
} else if ([firstByte isEqualToString:@"02"]) {
return @"https://www.";
} else if ([firstByte isEqualToString:@"03"]) {
return @"http://";
} else if ([firstByte isEqualToString:@"04"]) {
return @"https://";
} else if ([firstByte isEqualToString:@"05"]) {
return @"tel:";
} else if ([firstByte isEqualToString:@"06"]) {
return @"mailto:";
} else if ([firstByte isEqualToString:@"07"]) {
return @"ftp://anonymous:anonymous@";
} else if ([firstByte isEqualToString:@"08"]) {
return @"ftp://ftp.";
} else if ([firstByte isEqualToString:@"09"]) {
return @"ftps://";
} else if ([firstByte isEqualToString:@"0A"]) {
return @"sftp://";
} else if ([firstByte isEqualToString:@"0B"]) {
return @"smb://";
} else if ([firstByte isEqualToString:@"0C"]) {
return @"nfs://";
} else if ([firstByte isEqualToString:@"0D"]) {
return @"ftp://";
} else if ([firstByte isEqualToString:@"0E"]) {
return @"dav://";
} else if ([firstByte isEqualToString:@"0F"]) {
return @"news:";
} else if ([firstByte isEqualToString:@"10"]) {
return @"telnet://";
} else if ([firstByte isEqualToString:@"11"]) {
return @"imap:";
} else if ([firstByte isEqualToString:@"12"]) {
return @"rtsp://";
} else if ([firstByte isEqualToString:@"13"]) {
return @"urn:";
} else if ([firstByte isEqualToString:@"14"]) {
return @"pop:";
} else if ([firstByte isEqualToString:@"15"]) {
return @"sip:";
} else if ([firstByte isEqualToString:@"16"]) {
return @"sips:";
} else if ([firstByte isEqualToString:@"17"]) {
return @"tftp:";
} else if ([firstByte isEqualToString:@"18"]) {
return @"btspp://";
} else if ([firstByte isEqualToString:@"19"]) {
return @"btl2cap://";
} else if ([firstByte isEqualToString:@"1A"]) {
return @"btgoep://";
} else if ([firstByte isEqualToString:@"1B"]) {
return @"tcpobex://";
} else if ([firstByte isEqualToString:@"1C"]) {
return @"irdaobex://";
} else if ([firstByte isEqualToString:@"1D"]) {
return @"file://";
} else if ([firstByte isEqualToString:@"1E"]) {
return @"urn:epc:id:";
} else if ([firstByte isEqualToString:@"1F"]) {
return @"urn:epc:tag:";
} else if ([firstByte isEqualToString:@"20"]) {
return @"urn:epc:pat:";
} else if ([firstByte isEqualToString:@"21"]) {
return @"urn:epc:raw:";
} else if ([firstByte isEqualToString:@"22"]) {
return @"urn:epc:";
} else if ([firstByte isEqualToString:@"23"]) {
return @"urn:nfc:";
}
return @"";
}
/*!
* gets the the NDEF content
*/
- (NSString *)getNDEFContent:(NSData *)data {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return [dataString substringFromIndex:2];
}
/*!
* gets the first byte of the input NSData
*/
- (NSString *)getFirstByte:(NSData *)data {
return [[self dataToHexString:data] substringToIndex:2];
}
/*!
* transforms NSData to NSString
*/
- (NSString *)dataToHexString:(NSData *)data;
{
// get the length of the data
NSUInteger bytesCount = data.length;
if (bytesCount) {
// string with all the Hex characters
const char *hexChars = "0123456789ABCDEF";
// put bytes into an array and initialize the response array
const unsigned char *dataBuffer = data.bytes;
char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
char *s = chars;
// go through data bytes making the transformations so a hex will literally translate to a string, so for example 0x0A will translate to "0A"
for (unsigned i = 0; i < bytesCount; ++i) {
// get hexChars character at binary AND between the current byte and 0xF0 bitwise to the right by 4 index and assign it to the current chars pointer
*s++ = hexChars[((*dataBuffer & 0xF0) >> 4)];
// get hexChars character at binary AND between the current byte and 0x0F index and assign it to the current chars pointer
*s++ = hexChars[(*dataBuffer & 0x0F)];
dataBuffer++;
}
*s = '[=10=]';
// chars to string
NSString *hexString = [NSString stringWithUTF8String:chars];
free(chars);
return hexString;
}
return @"";
}
并调用getType
方法:
[self getType:yourNDEFPayloadNSData]
我假设所有方法都在同一个 class 和
负载 NSData 符合 NDEF,但我根据 NFCNDEFPayload
payload
对代码建模
关于您的 EDIT1:
您使用了错误的记录类型。
您需要写 "Text Record",而不是 "URI Record"。
如果您手边有 Android Phone,您可以使用 "NFC TagWriter by NFC" 之类的工具来写入正确的记录。
它对于您的用例可能并不重要,但请考虑与 Android Phones 的互操作性,resp。其他应用。他们会尝试打开“https://www.enhello 世界”而不是显示 "Hello World",使用 EN 编码作为文本字符串。
NFC NDEF 消息负载比您预期的要复杂得多。但 CoreNFC 不支持解析 NFC NDEF 消息负载。我创建了一个开源解析器 VYNFCKit to parse payload. Example projects are available in both Objective-C and Swift. Check my tutorial https://medium.com/@vinceyuan/reading-and-parsing-nfc-tag-on-ios-11-60f4bc7a11ea
我有一堆 URL 标签,内容为“http://WEBSITE.com". Let's say WEBSITE is youtube so http://youtube.com。当我在 Android 等上扫描它们时,它会保留 http 或 https。
我正在尝试使用核心 NFC 框架扫描这些相同的标签。我扫描它们并得到一堆字节,我使用带有 UTF8 编码的 NSSString initWithData 转换这些字节。我回来\^Cyoutube.com。我想得到 http://youtube.com.
我怎样才能拦截有效载荷以获得我需要的东西?如果我假设字符串前面有 http,我怎么知道它是 http 还是 https 甚至是 ftp?
编辑 1:
我在使用以下纯文本记录的答案代码时遇到问题。为 "hello world" 创建文本记录时,我从控制台获得以下输出:
2017-06-09 12:45:35.151806-0400 testNFC[2963:190724] 载荷字符串:https://www.enhello world
2017-06-09 12:45:35.154959-0400 testNFC[2963:190724] 载荷数据:<02656e68 656c6c6f 20776f72 6c64>
获取我使用的字符串
NSString *nfcMessage = [nfcType stringByAppendingString:[[[NSString alloc] initWithData:payload.payload encoding:NSUTF8StringEncoding] substringFromIndex:1]];
nfcType 是您函数中的 return 但对于 None 情况,我 return @"";
我希望得到 hello world。
为此,您首先需要确保您的 NDEF 标签格式正确。您可以使用 Android phone 或 these reader accessories along with an NDEF writing app 之一。
执行以下方法:
- (NSString *)getType:(NSData *)NDEFData {
NSString *firstByte = [self getFirstByte:NDEFData];
if ([firstByte isEqualToString:@"00"]) {
return @"None";
} else if ([firstByte isEqualToString:@"01"]) {
return @"http://www.";
} else if ([firstByte isEqualToString:@"02"]) {
return @"https://www.";
} else if ([firstByte isEqualToString:@"03"]) {
return @"http://";
} else if ([firstByte isEqualToString:@"04"]) {
return @"https://";
} else if ([firstByte isEqualToString:@"05"]) {
return @"tel:";
} else if ([firstByte isEqualToString:@"06"]) {
return @"mailto:";
} else if ([firstByte isEqualToString:@"07"]) {
return @"ftp://anonymous:anonymous@";
} else if ([firstByte isEqualToString:@"08"]) {
return @"ftp://ftp.";
} else if ([firstByte isEqualToString:@"09"]) {
return @"ftps://";
} else if ([firstByte isEqualToString:@"0A"]) {
return @"sftp://";
} else if ([firstByte isEqualToString:@"0B"]) {
return @"smb://";
} else if ([firstByte isEqualToString:@"0C"]) {
return @"nfs://";
} else if ([firstByte isEqualToString:@"0D"]) {
return @"ftp://";
} else if ([firstByte isEqualToString:@"0E"]) {
return @"dav://";
} else if ([firstByte isEqualToString:@"0F"]) {
return @"news:";
} else if ([firstByte isEqualToString:@"10"]) {
return @"telnet://";
} else if ([firstByte isEqualToString:@"11"]) {
return @"imap:";
} else if ([firstByte isEqualToString:@"12"]) {
return @"rtsp://";
} else if ([firstByte isEqualToString:@"13"]) {
return @"urn:";
} else if ([firstByte isEqualToString:@"14"]) {
return @"pop:";
} else if ([firstByte isEqualToString:@"15"]) {
return @"sip:";
} else if ([firstByte isEqualToString:@"16"]) {
return @"sips:";
} else if ([firstByte isEqualToString:@"17"]) {
return @"tftp:";
} else if ([firstByte isEqualToString:@"18"]) {
return @"btspp://";
} else if ([firstByte isEqualToString:@"19"]) {
return @"btl2cap://";
} else if ([firstByte isEqualToString:@"1A"]) {
return @"btgoep://";
} else if ([firstByte isEqualToString:@"1B"]) {
return @"tcpobex://";
} else if ([firstByte isEqualToString:@"1C"]) {
return @"irdaobex://";
} else if ([firstByte isEqualToString:@"1D"]) {
return @"file://";
} else if ([firstByte isEqualToString:@"1E"]) {
return @"urn:epc:id:";
} else if ([firstByte isEqualToString:@"1F"]) {
return @"urn:epc:tag:";
} else if ([firstByte isEqualToString:@"20"]) {
return @"urn:epc:pat:";
} else if ([firstByte isEqualToString:@"21"]) {
return @"urn:epc:raw:";
} else if ([firstByte isEqualToString:@"22"]) {
return @"urn:epc:";
} else if ([firstByte isEqualToString:@"23"]) {
return @"urn:nfc:";
}
return @"";
}
/*!
* gets the the NDEF content
*/
- (NSString *)getNDEFContent:(NSData *)data {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return [dataString substringFromIndex:2];
}
/*!
* gets the first byte of the input NSData
*/
- (NSString *)getFirstByte:(NSData *)data {
return [[self dataToHexString:data] substringToIndex:2];
}
/*!
* transforms NSData to NSString
*/
- (NSString *)dataToHexString:(NSData *)data;
{
// get the length of the data
NSUInteger bytesCount = data.length;
if (bytesCount) {
// string with all the Hex characters
const char *hexChars = "0123456789ABCDEF";
// put bytes into an array and initialize the response array
const unsigned char *dataBuffer = data.bytes;
char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
char *s = chars;
// go through data bytes making the transformations so a hex will literally translate to a string, so for example 0x0A will translate to "0A"
for (unsigned i = 0; i < bytesCount; ++i) {
// get hexChars character at binary AND between the current byte and 0xF0 bitwise to the right by 4 index and assign it to the current chars pointer
*s++ = hexChars[((*dataBuffer & 0xF0) >> 4)];
// get hexChars character at binary AND between the current byte and 0x0F index and assign it to the current chars pointer
*s++ = hexChars[(*dataBuffer & 0x0F)];
dataBuffer++;
}
*s = '[=10=]';
// chars to string
NSString *hexString = [NSString stringWithUTF8String:chars];
free(chars);
return hexString;
}
return @"";
}
并调用getType
方法:
[self getType:yourNDEFPayloadNSData]
我假设所有方法都在同一个 class 和
负载 NSData 符合 NDEF,但我根据
NFCNDEFPayload
payload
对代码建模
关于您的 EDIT1: 您使用了错误的记录类型。 您需要写 "Text Record",而不是 "URI Record"。 如果您手边有 Android Phone,您可以使用 "NFC TagWriter by NFC" 之类的工具来写入正确的记录。 它对于您的用例可能并不重要,但请考虑与 Android Phones 的互操作性,resp。其他应用。他们会尝试打开“https://www.enhello 世界”而不是显示 "Hello World",使用 EN 编码作为文本字符串。
NFC NDEF 消息负载比您预期的要复杂得多。但 CoreNFC 不支持解析 NFC NDEF 消息负载。我创建了一个开源解析器 VYNFCKit to parse payload. Example projects are available in both Objective-C and Swift. Check my tutorial https://medium.com/@vinceyuan/reading-and-parsing-nfc-tag-on-ios-11-60f4bc7a11ea