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