Wan Ammar
Wan Ammar

Reputation: 23

Sending text file using PN532 reader to NFC tag

Good day to you. I have build up a NFCTagFlow code to use in sending a text file to NFC Tag. It is a simplified version from using the RF881 reader My concern is there could be an unnecessary process to send the file to the tag

Is this correct?

public class NFCTagFlow {
    private Context context;

    public NFCTagFlow(Context context) {
        this.context = context;
    }

    public NdefMessage sendFileToTag(Tag detectedTag) {
        try {
            String filePath = "/storage/self/primary/Upload_in_NFC.txt";
            StringBuilder fileDataStringBuilder = new StringBuilder();

            // Read the file data into a buffer and get the string representation
            readFileToBuffer(filePath, fileDataStringBuilder);
            String fileContent = fileDataStringBuilder.toString();

            // Encode the file data into an NDEF message
            NdefMessage ndefMessage = encodeNdefData(fileContent);

            // Write the NDEF message to the NFC tag
            boolean success = writeNdefMessageToTag(detectedTag, ndefMessage);

            // If successful, return the NdefMessage, otherwise return null
            return success ? ndefMessage : null;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null; // Return null if writing failed
    }

    private void readFileToBuffer(String filePath, StringBuilder fileDataStringBuilder) throws IOException {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            throw new IOException("Invalid file path or file does not exist");
        }

        try (FileInputStream fis = new FileInputStream(file);
             InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
             BufferedReader br = new BufferedReader(isr)) {
            String line;
            while ((line = br.readLine()) != null) {
                fileDataStringBuilder.append(line);
            }
        }
    }

    private NdefMessage encodeNdefData(String data) {
        NdefRecord ndefRecord = createTextNdefRecord(data);
        return new NdefMessage(new NdefRecord[]{ndefRecord});
    }

    private NdefRecord createTextNdefRecord(String text) {
        byte[] language = Locale.getDefault().getLanguage().getBytes(StandardCharsets.US_ASCII);
        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
        int languageLength = language.length;
        int textLength = textBytes.length;

        byte[] payload = new byte[1 + languageLength + textLength];
        payload[0] = (byte) (languageLength & 0x1F);

        System.arraycopy(language, 0, payload, 1, languageLength);
        System.arraycopy(textBytes, 0, payload, 1 + languageLength, textLength);

        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
    }

    public boolean writeNdefMessageToTag(Tag detectedTag, NdefMessage ndefMessage) {
        Ndef ndef = Ndef.get(detectedTag);
        if (ndef != null) {
            try {
                ndef.connect();
                ndef.writeNdefMessage(ndefMessage);
                showToast("NDEF message written successfully");
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                showToast("Failed to write NDEF message");
            } finally {
                try {
                    ndef.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            showToast("NDEF not supported on this tag");
        }
        return false;
    }

    private void showToast(String message) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    }
}

Should I simplify more the code on the conversion of text file? Do help me if there's anything wrong or unnecessary code for the process of sending the text file to the nfc tag

Upvotes: 0

Views: 80

Answers (1)

Andrew
Andrew

Reputation: 10232

So you could simplify the code a bit.

From API 21 uploads there is the static method createTextRecord available that allows you to easily create a Ndef Text Record this would replace your createTextNdefRecord method.

Your code also probably breaks some NFC guidelines. It looks like you run this code on the UI thread as you show a toast message directly. The writeNdefMessage says

This is an I/O operation and will block until complete. It must not be called from the main application thread

You have not shown how you obtained the Tag object but I guess you used Intents/enableForegroundDispatch but with these you need to do your own work to put them on a non UI thread. They are also do not produce a very reliable NFC write experience. Better to use the enableReaderMode method of Tag detection.

Upvotes: 1

Related Questions