如何向单个NFC标签写入双字符串?Android考勤应用开发求助
NFC考勤应用代码修复方案
问题根源
- 重复写入会覆盖数据:原代码两次调用
write方法,每次写入单独的NDEF消息,第二次写入会完全覆盖第一次的内容,最终标签只保留第二个数据。 - 文本记录创建错误:
createRecord方法里错误地将语言字节数组复制到文本区域,导致实际写入的文本内容错乱。 - 读取逻辑不完整:只读取了第一个NDEF记录,第二个输入框始终显示空值。
修改后的完整代码
import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.nfc.FormatException; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.Ndef; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; public class writeHome extends AppCompatActivity { public static final String Error_Detected = "No NFC Tag Detected!"; public static final String Write_Success = "Text Written Successfully!"; public static final String Write_Error = "Error during Writing, Try again!"; NfcAdapter nfcAdapter; PendingIntent pendingIntent; IntentFilter[] writingTagFilters; boolean writeMode; Tag myTag; Context context; TextView editTextTextPersonName7; TextView editTextTextPersonName3; Button button2; @RequiresApi(api = Build.VERSION_CODES.S) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_write_home); editTextTextPersonName7 = findViewById(R.id.editTextTextPersonName7); editTextTextPersonName3 = findViewById(R.id.editTextTextPersonName3); button2 = findViewById(R.id.button2); context = this; // 修改:合并两个数据的写入逻辑,避免覆盖 button2.setOnClickListener(view -> { try { if(myTag == null) { Toast.makeText(context, Error_Detected, Toast.LENGTH_LONG).show(); } else { writeTwoRecords(editTextTextPersonName7.getText().toString(), editTextTextPersonName3.getText().toString(), myTag); Toast.makeText(context, Write_Success, Toast.LENGTH_SHORT).show(); } } catch (IOException | FormatException e) { Toast.makeText(context, Write_Error, Toast.LENGTH_LONG).show(); e.printStackTrace(); } }); nfcAdapter = NfcAdapter.getDefaultAdapter(this); if(nfcAdapter == null) { Toast.makeText(this, "This device does not support NFC!", Toast.LENGTH_SHORT).show(); } readFromIntent(getIntent()); pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); tagDetected.addCategory(Intent.CATEGORY_DEFAULT); writingTagFilters = new IntentFilter[] { tagDetected }; } private void readFromIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage[] msgs = null; if (rawMsgs != null) { msgs = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { msgs[i] = (NdefMessage) rawMsgs[i]; } } buildTagViews(msgs); } } // 修改:读取并显示两个NDEF记录 private void buildTagViews(NdefMessage[] msgs) { if (msgs == null || msgs.length == 0) return; String text1 = ""; String text2 = ""; // 获取第一个消息里的所有记录 NdefRecord[] records = msgs[0].getRecords(); // 处理第一个记录 if (records.length > 0) { byte[] payload = records[0].getPayload(); String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; int languageCodeLength = payload[0] & 51; try { text1 = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding); } catch (UnsupportedEncodingException e) { Log.e("UnsupportedEncoding", e.toString()); } } // 处理第二个记录 if (records.length > 1) { byte[] payload = records[1].getPayload(); String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; int languageCodeLength = payload[0] & 51; try { text2 = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding); } catch (UnsupportedEncodingException e) { Log.e("UnsupportedEncoding", e.toString()); } } // 显示到对应输入框 editTextTextPersonName7.setText(text1); editTextTextPersonName3.setText(text2); } // 新增:一次性写入两个NDEF记录 private void writeTwoRecords(String text1, String text2, Tag tag) throws IOException, FormatException { NdefRecord[] records = { createRecord(text1), createRecord(text2) }; NdefMessage message = new NdefMessage(records); Ndef ndef = Ndef.get(tag); ndef.connect(); ndef.writeNdefMessage(message); ndef.close(); } // 修改:修复文本字节复制错误 private NdefRecord createRecord(String text) { String lang = "en"; byte[] textBytes = text.getBytes(StandardCharsets.UTF_8); byte[] langBytes = lang.getBytes(StandardCharsets.US_ASCII); int langLength = langBytes.length; int textLength = textBytes.length; byte[] payload = new byte[1 + langLength + textLength]; payload[0] = (byte) langLength; System.arraycopy(langBytes, 0, payload, 1, langLength); // 原错误:复制了langBytes,现在改为复制textBytes System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength); return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); readFromIntent(intent); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); } } @Override public void onPause() { super.onPause(); WriteModeOff(); } @Override public void onResume() { super.onResume(); WriteModeOn(); } private void WriteModeOn() { writeMode = true; String[][] techList = new String[][] { { android.nfc.tech.Ndef.class.getName() }, { android.nfc.tech.NdefFormatable.class.getName() } }; nfcAdapter.enableForegroundDispatch(this, pendingIntent, writingTagFilters, techList); } private void WriteModeOff() { writeMode = false; nfcAdapter.disableForegroundDispatch(this); } }
关键修改说明
合并写入逻辑
新增writeTwoRecords方法,将两个文本分别创建为NDEF记录,打包成一个NDEF消息后一次性写入标签,避免两次写入导致的数据覆盖。同时修改按钮点击事件,调用这个新方法。修复记录创建错误
在createRecord方法中,把错误的System.arraycopy(langBytes, 0, payload, 1+langLength, textLength)改为System.arraycopy(textBytes, 0, payload, 1+langLength, textLength),确保实际写入的是输入的文本内容。完善读取逻辑
修改buildTagViews方法,遍历NDEF消息中的多个记录,分别读取第一个和第二个记录的内容,并显示到对应的输入框中。
内容的提问来源于stack exchange,提问作者Student Progg
相关产品推荐
相关产品推荐

