Search code examples
xamarinxamarin.formsencodingnfc

Cannot Decode NFC Message


I am developing a Xamarin Forms app which opens up a view with the view model being determined by data transferred via an NFC tag using the Plugins.NFC package. I have functionality to encode an ID to the tag as well as read the tag. My problem is, it seems that when the NFC tag is read, I cannot do anything with the resulting string as it throws an error due to what I believe is it not being decoded correctly.

I have tried two different methods of structuring the data on the NFC chip such as a JSON object as well as just an ID of the object. What's weird is when I set a breakpoint after reading the tag, the string appears to look fine and show up, and JsonLint even responded with the JSON being valid when I attempted to use JSON in the tag. The error is thrown once I begin to use the string of the tag content in any way. When I was trying to use JSON in the tag, and I would go to deserialize it, I would get an error saying that there was a parsing error at line 0 position 0.

When I am trying to use an ID (int) in the tag, when I try to parse it I get the error "Input string was not in the correct format" Now I've determined that it's got to be something with encoding / decoding the NFC tag because if I use an app to write something to the tag, it works flawlessly, but when I write to the tag in my app, that's when the issue arises.

This is the function to read the tag. Notice the commented code as previous attempts to decode.

async void Current_OnMessageReceived(ITagInfo tagInfo)
    {
        if (tagInfo == null)
        {
            await ShowAlert("No tag found");
            return;
        }

        // Customized serial number
        var identifier = tagInfo.Identifier;
        var serialNumber = NFCUtils.ByteArrayToHexString(identifier, ":");
        var title = !string.IsNullOrWhiteSpace(serialNumber) ? $"Tag [{serialNumber}]" : "Tag Info";

        if (!tagInfo.IsSupported)
        {
            await ShowAlert("Unsupported tag (app)", title);
        }
        else if (tagInfo.IsEmpty)
        {
            await ShowAlert("Empty tag", title);
        }
        else
        {
            IDatabaseManager db = TinyIoCContainer.Current.Resolve<IDatabaseManager>() as IDatabaseManager;
            //var first = tagInfo.Records[0];
            //string msg = first.Message;
            //string msgHex = NFCUtils.ByteArrayToHexString(tagInfo.Records[0].Payload);
            //string msg = Convert.ToString(msgHex);
            //string msg = NFCUtils.GetMessage(tagInfo.Records[0]);
            string msg = NFCUtils.GetMessage(tagInfo.Records[0]);
            try
            { 
                //tring messageEncoded = Encoding.UTF8.GetString(tagInfo.Records[0].Payload);
                int cardId = int.Parse(msg);
                var card = await db.GetCard(cardId);
                //Entities.Card card = JsonConvert.DeserializeObject<Entities.Card>(msg);
                var model = await CardModel.FromCard(card);
                await Application.Current.MainPage.Navigation.PushAsync(new ViewCardPage(model));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

And Here is the function that writes to the tag

void Current_OnTagDiscovered(ITagInfo tagInfo, bool format)
    {
        if (!CrossNFC.Current.IsWritingTagSupported)
        {
            return;
        }

        try
        {
            var record = new NFCNdefRecord
            {
                TypeFormat = NFCNdefTypeFormat.WellKnown,
                MimeType = "text/plain",
                Payload = NFCUtils.EncodeToByteArray(selectedCard.Card.Id.ToString())
                //Payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(selectedCard.Card);)
            };

            if (!format && record == null)
                throw new Exception("Record can't be null.");

            tagInfo.Records = new[] { record };

            //if (format)
            //{ 
            //  CrossNFC.Current.ClearMessage(tagInfo);
            //}

            CrossNFC.Current.PublishMessage(tagInfo, false);
        }
        catch (System.Exception ex)
        {
            //await ShowAlert(ex.Message);
            return;
        }
    }

Reading tag breakpoint hit


Solution

  • So it seems that this could be an issue with the Plugin.NFC package. The workaround I've found was that if I use a URI rather than text, it was encoded correctly.