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

时间:2017-06-08 20:40:09

标签: ios xcode nfc ndef

我有一堆标签,这些标签是包含内容" http://WEBSITE.com"的网址标记。让我们说WEBSITE是youtube所以http://youtube.com。当我在Android等上扫描它们时,它会保留http或https。

我尝试使用Core NFC框架扫描这些相同的标签。我扫描它们,我得到一堆字节,我使用NSSString initWithData和UTF8编码转换。我回来了\ ^ 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 656c6c6f 20776f72 6c64>

获取我使用的字符串

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

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

我希望能得到你好的世界。

3 个答案:

答案 0 :(得分:4)

为此,您首先需要确保已正确格式化NDEF标记。您可以使用Android手机或these reader accessories以及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 = '\0';
        // chars to string
        NSString *hexString = [NSString stringWithUTF8String:chars];
        free(chars);
        return hexString;
    }
    return @"";
}

并调用getType方法:

[self getType:yourNDEFPayloadNSData]
  • 我假设所有方法属于同一类,

  • 有效负载NSData符合NDEF,但我根据NFCNDEFPayload payload

  • 对代码建模

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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