iOS 11 - 如何从CoreNFC读取/解析NDEF消息?



我有一堆标签,这些标签是内容为"http://WEBSITE.com"的URL标签。假设网站是YouTube,所以 http://youtube.com。当我在安卓等上扫描它们时,它会保留http或https。

我正在尝试使用Core 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 世界

2017-06-09 12:45:35.154959-0400 testNFC[2963:190724] 有效载荷数据:<02656e68>

获取我使用的字符串

NSString *nfcMessage = [nfcType stringByAppendingString:[[[NSString alloc] initWithData:payload.payload encoding:NSUTF8StringEncoding] substringFromIndex:1]];

nfcType 是函数的返回,但对于 None 的情况,我返回 @";

我期待只是得到你好世界。

为此,您首先需要确保具有正确格式的 NDEF 标记。您可以使用Android手机或这些阅读器配件之一以及NDEF书写应用程序。

实现以下方法:

- (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 = '';
// chars to string
NSString *hexString = [NSString stringWithUTF8String:chars];
free(chars);
return hexString;
}
return @"";
}

并调用getType方法:

[self getType:yourNDEFPayloadNSData]
  • 我假设所有方法都在同一个类中,并且,

  • 有效载荷 NSData 符合 NDEF,但我根据代码建模NFCNDEFPayloadpayload

NFC NDEF 消息有效负载比您预期的要复杂得多。但 CoreNFC 不支持解析 NFC NDEF 消息有效负载。我创建了一个开源解析器VYNFCKit来解析有效负载。示例项目在 Objective-C 和 Swift 中都可用。查看我的教程 https://medium.com/@vinceyuan/reading-and-parsing-nfc-tag-on-ios-11-60f4bc7a11ea

关于您的 EDIT1: 您使用了错误的记录类型。 您需要编写"文本记录",而不是"URI 记录"。 如果你手头有一部Android手机,你可以使用"NFC TagWriter by NFC"这样的工具来写正确的记录。 这对您的用例可能并不重要,但请考虑与 Android 手机或其他应用程序的互操作性。他们会尝试打开"https://www.enhello 世界"而不是显示"Hello World",使用EN编码作为文本字符串。

最新更新