NFCForms
NFCForms copied to clipboard
[Request] Format Tag when NdefFormatable is found
Like the title says. It would be grand if the WriteTag would include a check if NdefFormatable is present and write to the chip using Android.Nfc.Tech.NdefFormatable.Format.
So i dove into your code and did it myself. Im sure it can be done in a cleaner way but this worked for me Droid/NfcForms.cs
public void WriteTag (NdefLibrary.Ndef.NdefMessage message)
{
if (droidTag == null)
{
throw new Exception("Tag Error: No Tag to write, register to NewTag event before calling WriteTag()");
}
Ndef ndef = GetNdef (droidTag);
//Check if the tag can be NDEFformatted
var formatcheck = nfcTag.TechList.Contains(NFCTechs.NdefFormatable);
//Previous check didnt compare both just ndef being null can also mean its not formatted
if (ndef == null && formatcheck == false)
{
throw new Exception("Tag Error: NDEF not supported");
}
//Not formatted but can be formatted
if (ndef == null && formatcheck == true)
{
NdefFormatable formatable = NdefFormatable.Get(droidTag);
//For some reason this could still give null even if formatcheck gave a true so /shrug
if (formatable == null)
{
throw new Exception("Tag Error: NDEFformat not supported");
}
try
{
formatable.Connect();
RaiseTagConnected(nfcTag);
}
catch
{
throw new Exception("Tag Error: No Tag nearby");
}
//old size check.
//int size = message.ToByteArray().Length;
try
{
List<Android.Nfc.NdefRecord> records = new List<Android.Nfc.NdefRecord>();
for (int i = 0; i < message.Count; i++)
{
if (message[i].CheckIfValid())
records.Add(new Android.Nfc.NdefRecord(Android.Nfc.NdefRecord.TnfWellKnown, message[i].Type, message[i].Id, message[i].Payload));
else
{
throw new Exception("NDEFRecord number " + i + "is not valid");
}
};
Android.Nfc.NdefMessage msg = new Android.Nfc.NdefMessage(records.ToArray());
//This Format works with Mifare Classic and NTAG213. Fails with ultralight. these are the chips I tested it with.
//Both with pre used ones and with factory new ones.
formatable.Format(msg);
}
catch (TagLostException tle)
{
throw new Exception("Tag Lost Error: " + tle.Message);
}
catch (IOException ioe)
{
throw new Exception("Tag IO Error: " + ioe.ToString());
}
catch (Android.Nfc.FormatException fe)
{
throw new Exception("Tag Format Error: " + fe.Message);
}
catch (Exception e)
{
//Assume that if we are here the tag is still touching the device, our message is correct, and the tag isnt busted.
try
{
//we close this tech so we can open it as ultralight
formatable.Close();
//check if the connected chip is ultralight.
if (droidTag.GetTechList().Contains(NFCTechs.MifareUltralight))
{
MifareUltralight ultralight = MifareUltralight.Get(droidTag);
if (ultralight != null)
{
try
{
//connect with ultralight tech
ultralight.Connect();
//Found this on a stackoverflow question that had the same problem, apparently this sets it up to be NFC Forum Type 2 tag.
ultralight.Transceive(new byte[]
{
(byte)0xA2,//Write
(byte)0x03,//Page Nr = 3
(byte)0xE1,(byte)0x10,(byte)0x06, (byte)0x00//capability container (mapping version 1.0, 48 bytes for data available, read/ write allowed)
});
ultralight.Transceive(new byte[]
{
(byte)0xA2,//Write
(byte)0x04,//Page nr = 4
(byte)0x03, (byte)0x00,(byte)0xFE,(byte)0x00 // empty NDEF TLV, Terminator TLV
});
}catch(Exception e1)
{
}
finally
{
//Now the tag is formatted to accept NDEF
try
{
//Close this tech connection as this one doesnt have WriteNdef
ultralight.Close();
//Get the tag as Ndef
ndef = GetNdef(droidTag);
//Connect
ndef.Connect();
//Check the message again JIC
List<Android.Nfc.NdefRecord> recordsFormat = new List<Android.Nfc.NdefRecord>();
for (int i = 0; i < message.Count; i++)
{
if (message[i].CheckIfValid())
recordsFormat.Add(new Android.Nfc.NdefRecord(Android.Nfc.NdefRecord.TnfWellKnown, message[i].Type, message[i].Id, message[i].Payload));
else
{
throw new Exception("NDEFRecord number " + i + "is not valid");
}
};
Android.Nfc.NdefMessage msg = new Android.Nfc.NdefMessage(recordsFormat.ToArray());
//Write and close
ndef.WriteNdefMessage(msg);
ndef.Close();
}
catch
{
}
}
}
}
}
catch(Exception eform)
{
//
throw new Exception("Tag Error: " + eform.ToString());
}
}
finally
{
//Used to not have the ultralight code in so i had to close here
//formatable.Close();
RaiseTagTagDisconnected(nfcTag);
}
}
else
{
//Rest as normal
try
{
ndef.Connect();
RaiseTagConnected(nfcTag);
}
catch
{
throw new Exception("Tag Error: No Tag nearby");
}
if (!ndef.IsWritable)
{
ndef.Close();
throw new Exception("Tag Error: Tag is write locked");
}
int size = message.ToByteArray().Length;
if (ndef.MaxSize < size)
{
ndef.Close();
throw new Exception("Tag Error: Tag is too small");
}
else
{
try
{
List<Android.Nfc.NdefRecord> records = new List<Android.Nfc.NdefRecord>();
for (int i = 0; i < message.Count; i++)
{
if (message[i].CheckIfValid())
records.Add(new Android.Nfc.NdefRecord(Android.Nfc.NdefRecord.TnfWellKnown, message[i].Type, message[i].Id, message[i].Payload));
else
{
throw new Exception("NDEFRecord number " + i + "is not valid");
}
};
Android.Nfc.NdefMessage msg = new Android.Nfc.NdefMessage(records.ToArray());
ndef.WriteNdefMessage(msg);
}
catch (TagLostException tle)
{
throw new Exception("Tag Lost Error: " + tle.Message);
}
catch (IOException ioe)
{
throw new Exception("Tag IO Error: " + ioe.ToString());
}
catch (Android.Nfc.FormatException fe)
{
throw new Exception("Tag Format Error: " + fe.Message);
}
catch (Exception e)
{
throw new Exception("Tag Error: " + e.ToString());
}
finally
{
ndef.Close();
RaiseTagTagDisconnected(nfcTag);
}
}
}
}