package com.app.jleung.nfctagger;

import android.content.Intent;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class NfcReader {

    private static final String MIME_TEXT_PLAIN = "text/plain";

    public String readTagFromIntent(Intent intent) throws NfcReadFailureException {
        // No tag when you startup the application
        if(intent.getAction().equals("android.intent.action.MAIN")) {
            return null;
        }
        else if(!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            throw new NfcReadFailureException(NfcReadFailureException.Reason.INVALID_TAG_TYPE);
        }
        else if(!MIME_TEXT_PLAIN.equals(intent.getType())) {
            throw new NfcReadFailureException(NfcReadFailureException.Reason.INVALID_CONTENT_TYPE);
        }

        return readTag((Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
    }

    private String readTag(Tag tag) throws NfcReadFailureException {
        Ndef ndef = Ndef.get(tag);
        if(ndef == null) {
            return null;
        }

        NdefRecord extractedRecord = null;
        NdefRecord[] ndefRecords = ndef.getCachedNdefMessage().getRecords();
        for(NdefRecord ndefRecord : ndefRecords) {
            if(ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN &&
                    Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                extractedRecord = ndefRecord;
                break;
            }
        }

        if(extractedRecord == null) {
            return null;
        }

        return readTagText(extractedRecord);
    }

    /**
     * See NFC forum specification for Text Record Type Definition at 3.2.1
     * http://www.nfc-forum.org/specs
     *
     * @param ndefRecord
     * @return
     * @throws UnsupportedEncodingException
     */
    private String readTagText(NdefRecord ndefRecord) throws NfcReadFailureException {
        byte[] payload = ndefRecord.getPayload();
        int languageCodeLength = payload[0] & 0063;
        String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";

        try {
            return new String(
                    payload,
                    languageCodeLength + 1,
                    payload.length - languageCodeLength - 1,
                    textEncoding
            );
        }
        catch(UnsupportedEncodingException e) {
            throw new NfcReadFailureException(NfcReadFailureException.Reason.INVALID_ENCODING);
        }
    }

    public static class NfcReadFailureException extends Exception {

        private Reason reason;

        public NfcReadFailureException(Reason reason) {
            super();
            this.reason = reason;
        }

        public Reason getReason() {
            return reason;
        }

        public static enum Reason {
            INVALID_TAG_TYPE("Invalid tag type; NDEF is required"),
            INVALID_CONTENT_TYPE("Invalid content type; text/plain is required"),
            INVALID_ENCODING("Invalid text encoding");

            private String text;

            private Reason(String text) {
                this.text = text;
            }

            public String getText() {
                return text;
            }
        }
    }

}

@@ -174,16 +174,41 @@
 ch.Ndef;
+%0Aimport android.util.Log;
 %0A%0Aimport
@@ -294,24 +294,96 @@
 fcReader %7B%0A%0A
+    private static final String TAG = NfcReader.class.getSimpleName();%0A%0A
     private 
@@ -636,24 +636,93 @@
 n.MAIN%22)) %7B%0A
+            Log.d(TAG, %22Startup Intent detected - no action taken%22);%0A
             
@@ -1275,16 +1275,19 @@
 def ndef
+Tag
  = Ndef.
@@ -1311,16 +1311,19 @@
  if(ndef
+Tag
  == null
@@ -1334,35 +1334,106 @@
             
-return null
+throw new NfcReadFailureException(NfcReadFailureException.Reason.INVALID_TAG_TYPE)
 ;%0A        %7D%0A
@@ -1476,32 +1476,36 @@
 = null;%0A        
+for(
 NdefRecord%5B%5D nde
@@ -1498,18 +1498,16 @@
 efRecord
-%5B%5D
  ndefRec
@@ -1513,16 +1513,18 @@
 cord
-s =
+ :
  ndef
+Tag
 .get
@@ -1559,57 +1559,8 @@
 ds()
-;%0A        for(NdefRecord ndefRecord : ndefRecords
 ) %7B%0A
@@ -1791,33 +1791,32 @@
     %7D%0A        %7D%0A
-%0A
         if(extra
@@ -1848,36 +1848,34 @@
          return 
-null
+%22%22
 ;%0A        %7D%0A%0A   
@@ -2223,32 +2223,93 @@
 lureException %7B%0A
+        Log.d(TAG, %22Reading NDEF record from tag payload%22);%0A%0A
         byte%5B%5D p
@@ -2469,24 +2469,45 @@
  %22UTF-16%22;%0A%0A
+        String data;%0A
         try 
@@ -2520,22 +2520,22 @@
         
-return
+data =
  new Str
@@ -2876,32 +2876,109 @@
 DING);%0A        %7D
+%0A%0A        Log.d(TAG, %22Parsed tag data: %5B%22 + data + %22%5D%22);%0A        return data;
 %0A    %7D%0A%0A    publ

Improve usability of NfcReader