【问题标题】:How to write values to NFC tag from two activities without overwriting existing values?如何在不覆盖现有值的情况下从两个活动将值写入 NFC 标签?
【发布时间】:2018-09-07 14:08:27
【问题描述】:

我正在尝试编写一个具有两个活动的 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;
}
}

有没有办法做到这一点?

【问题讨论】:

    标签: java android nfc overwrite ndef


    【解决方案1】:

    一个 NFC Forum 类型的标签只能包含一个 NDEF 消息。因此,ndef.writeNdefMessage(ndefMessage) 方法将始终使用作为参数 ndefMessage 传递的新消息覆盖任何现有的 NDEF 消息。

    当然,该 NDEF 消息可能包含任意数量的 NDEF 记录(或者实际上适合您的标签)。

    如果您想保留现有数据,则需要先阅读现有的 NDEF 消息,例如由

    Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    if (parcelables != null && parcelables.length > 0) {
        NdefMessage ndefMessage = (NdefMessage)parcelables[0];
        ...
    

    然后您可以解析此消息并保留/删除您想要保留/删除的部分(NDEF 记录或数据元素)。最后,您会将新部分添加到该消息中,然后将整个消息再次写入标签。

    【讨论】:

    • 如果我理解正确的话,我可以在一个 NDEF 消息中仅从一个活动写入多条记录,因为仍然无法使用来自另一个活动的新信息写入标签,因为只有一个 NDEF 消息可以写入标签
    • @DaGuy 在 Android 上,任何时候只有一个活动(前台活动)作为对 NFC 标签的访问。因此,如果您想保留之前存储在标签上的数据(使用另一个活动),第二个活动需要读取数据,添加自己的数据并将所有内容再次存储在标签上。您可以在一个标签上放置任意数量的记录(只要有足够的可用存储空间)。
    • 我可以避免读取第一个活动写入标签的内容并从第二个活动向标签写入新信息吗?
    • 我会详细解释我想要做什么。我有 2 个活动(可以读写),两者都有相同的代码,第一个活动写一个人名和国家,而第二个活动写一个人的兴趣和爱好。在第一个活动将信息写入标签后,两个活动都可以读取信息,并且信息被第二个活动覆盖(当我写人的兴趣和爱好时)
    • @DaGuy 在写入新数据之前读取旧数据有什么问题?无论如何,所有这些都发生在一次点击中。总的来说,我不确定我是否理解您为什么甚至想要从这两个活动中写入数据。在我看来,用户无论如何都会通过这两个活动(将两个数据集都写入标签)。如果是这种情况,最好将第一个活动的信息传递给第二个活动,并且只将聚合数据集写入第二个活动的标签。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多