Reputation: 23
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
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