Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request] Format Tag when NdefFormatable is found #34

Open
Gekidoku opened this issue Jan 14, 2019 · 1 comment
Open

[Request] Format Tag when NdefFormatable is found #34

Gekidoku opened this issue Jan 14, 2019 · 1 comment

Comments

@Gekidoku
Copy link

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.

@Gekidoku
Copy link
Author

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);
                    }
                }
            }

		}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant