Как записать значения в тег NFC из двух действий без перезаписи существующих значений?
Я пытаюсь написать приложение для Android с двумя действиями, которые записывают несколько значений (строки / текст) в один и тот же тег NFC. Мне удалось выполнить одно действие, чтобы записать значения в тег, но как я могу предотвратить перезапись значения второго действия во втором действии?
public class MainActivity extends AppCompatActivity {
NfcAdapter nfcAdapter;
ToggleButton tglReadWrite;
Button anotherActivtybtn;
EditText txtName;
EditText txtCountry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
tglReadWrite = (ToggleButton)findViewById(R.id.tglReadWrite);
txtName = (EditText)findViewById(R.id.idName);
txtCountry= (EditText)findViewById(R.id.idCountry);
anotherActivtybtn= (Button)findViewById(R.id.anotherActivtybtn);
anotherActivtybtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent= new Intent(MainActivity.this, AnotherActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onResume() {
super.onResume();
if(nfcAdapter !=null){
/* go to phone's nfc settings */
if(!nfcAdapter.isEnabled()){
showNfcSettings();
}
enableForegroundDispatchSystem();
}
}
private void showNfcSettings() {
Intent nfcSettingIntent = new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(nfcSettingIntent);
}
@Override
protected void onPause() {
super.onPause();
disableForegroundDispatchSystem();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
Toast.makeText(this, "NfcIntent!", Toast.LENGTH_SHORT).show();
if(tglReadWrite.isChecked())
{
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(parcelables != null && parcelables.length > 0)
{
readTextFromMessage((NdefMessage) parcelables[0]);
}else{
Toast.makeText(this, "No NDEF messages found!", Toast.LENGTH_SHORT).show();
}
}else{
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NdefMessage ndefMessage = createNdefMessage(txtName.getText().toString(), txtCountry.getText().toString());
writeNdefMessage(tag, ndefMessage);
}
}
}
private void readTextFromMessage(NdefMessage ndefMessage) {
NdefRecord[] ndefRecords = ndefMessage.getRecords();
if(ndefRecords != null && ndefRecords.length>0){
NdefRecord ndefRecord = ndefRecords[0];
NdefRecord ndefRecord2 = ndefRecords[1];
String tagContent = getTextFromNdefRecord(ndefRecord);
String tagContent2 = getTextFromNdefRecord(ndefRecord2);
txtName.setText(tagContent);
txtCountry.setText(tagContent2);
}else
{
Toast.makeText(this, "No NDEF records found!", Toast.LENGTH_SHORT).show();
}
}
private void enableForegroundDispatchSystem() {
Intent intent = new Intent(this, MainActivity.class).addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
IntentFilter[] intentFilters = new IntentFilter[]{};
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null);
}
private void disableForegroundDispatchSystem() {
nfcAdapter.disableForegroundDispatch(this);
}
private void formatTag(Tag tag, NdefMessage ndefMessage) {
try {
NdefFormatable ndefFormatable = NdefFormatable.get(tag);
if (ndefFormatable == null) {
Toast.makeText(this, "Tag is not ndef formatable!", Toast.LENGTH_SHORT).show();
}
else{
ndefFormatable.connect();
ndefFormatable.format(ndefMessage);
ndefFormatable.close();
Toast.makeText(this, "Tag writen!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("formatTag", e.getMessage());
}
}
private void writeNdefMessage(Tag tag, NdefMessage ndefMessage) {
try {
if (tag == null) {
Toast.makeText(this, "Tag object cannot be null", Toast.LENGTH_SHORT).show();
return;
}
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// format tag with the ndef format and writes the message.
formatTag(tag, ndefMessage);
} else {
ndef.connect();
if (!ndef.isWritable()) {
Toast.makeText(this, "Tag is not writable!", Toast.LENGTH_SHORT).show();
ndef.close();
return;
}
ndef.writeNdefMessage(ndefMessage);
ndef.close();
Toast.makeText(this, "Tag writen!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("writeNdefMessage", e.getMessage());
}
}
private NdefRecord createTextRecord(String content) {
try {
byte[] language;
language = Locale.getDefault().getLanguage().getBytes("UTF-8");
final byte[] text = content.getBytes("UTF-8");
final int languageSize = language.length;
final int textLength = text.length;
final ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + languageSize + textLength);
payload.write((byte) (languageSize & 0x1F));
payload.write(language, 0, languageSize);
payload.write(text, 0, textLength);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());
} catch (UnsupportedEncodingException e) {
Log.e("createTextRecord", e.getMessage());
}
return null;
}
private NdefMessage createNdefMessage(String content, String content2) {
NdefRecord ndefRecord = createTextRecord(content);
NdefRecord ndefRecord2 = createTextRecord(content2);
NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{ndefRecord, ndefRecord2});
return ndefMessage;
}
public void tglReadWriteOnClick(View view){
txtName.setText("");
txtCountry.setText("");
}
public String getTextFromNdefRecord(NdefRecord ndefRecord)
{
String tagContent = null;
try {
byte[] payload = ndefRecord.getPayload();
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
int languageSize = payload[0] & 0063;
tagContent = new String(payload, languageSize + 1,
payload.length - languageSize - 1, textEncoding);
} catch (UnsupportedEncodingException e) {
Log.e("getTextFromNdefRecord", e.getMessage(), e);
}
return tagContent;
}
}
Есть способ сделать это?
1 ответ
Тег типа NFC Forum может содержать только одно сообщение NDEF. Следовательно, метод ndef.writeNdefMessage(ndefMessage)
всегда будет перезаписывать любое существующее сообщение NDEF новым сообщением, переданным в качестве аргумента ndefMessage
,
Это сообщение NDEF может, конечно, состоять из любого количества записей NDEF, которые вам нравятся (или фактически соответствуют вашему тегу).
Если вы хотите сохранить существующие данные, вам необходимо сначала прочитать существующее сообщение NDEF, например,
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (parcelables != null && parcelables.length > 0) {
NdefMessage ndefMessage = (NdefMessage)parcelables[0];
...
Затем вы можете проанализировать это сообщение и сохранить / удалить части (записи NDEF или элементы данных), которые вы хотели бы сохранить / удалить. Наконец, вы должны добавить свои новые части к этому сообщению и снова записать все сообщение в тег.