如何在不覆盖现有值的情况下将两个活动的值写入 NFC 标签?
How to write values to NFC tag from two activities without overwriting existing values?
我正在尝试编写一个 Android 应用程序,该应用程序具有两个将多个值 (Strings/text) 写入同一个 NFC 标签的活动。我已经设法让一个 activity 将值写入标签,但是如何防止第二个 activity 覆盖第一个 activity 的值?
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;
}
}
有办法吗?
一个 NFC 论坛类型标签只能包含一个 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];
...
然后您可以解析此消息和 keep/drop 您想要 preserve/remove 的部分(NDEF 记录或数据元素)。最后,您可以将新部分添加到该消息并将整个消息再次写入标签。
我正在尝试编写一个 Android 应用程序,该应用程序具有两个将多个值 (Strings/text) 写入同一个 NFC 标签的活动。我已经设法让一个 activity 将值写入标签,但是如何防止第二个 activity 覆盖第一个 activity 的值?
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;
}
}
有办法吗?
一个 NFC 论坛类型标签只能包含一个 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];
...
然后您可以解析此消息和 keep/drop 您想要 preserve/remove 的部分(NDEF 记录或数据元素)。最后,您可以将新部分添加到该消息并将整个消息再次写入标签。