How to stop overwrite to an NFC tag using Android

青春壹個敷衍的年華 提交于 2019-12-13 18:28:52

问题


I'm using PN512 in card emulation mode as a NFC tag and am developing an Android application to read and write into the tag. The problem is, as long as the tag is in the NFC field, the program will keep reading and writing to the tag, but I want stop the program from overwriting the same tag once successfully writen. Are there any solutions for that?

(I know there is no way to programmatically disable NFC based on Android SDK)

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    btn = (Button) findViewById(R.id.btn_OK);
    mEditText = (EditText) findViewById(R.id.text_username);
    btn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            prefs = getSharedPreferences(prefName, MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putString(TEXT_VALUE_KEY, mEditText.getText().toString());
            editor.commit();

            String outtxt = "please touch and hold phone to tag";
            Toast toastedit12 = Toast.makeText(getApplicationContext(), outtxt, Toast.LENGTH_SHORT);
            toastedit12.show();
        }
    });

    resolveIntent(getIntent());
}


// This method/task executes when the tag is read
void resolveIntent(Intent intent)
{
    NdefMessage msg1, msg2;
    // Parse the intent
    String action = intent.getAction();

    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) ||
        NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

        try
        {
            mRecord=createRecord();
        }
        catch (Exception e)
        {
            Toast toaste = Toast.makeText(getApplicationContext(), "exception in call to create record", Toast.LENGTH_SHORT);
            toaste.show();
        }

        // When a tag is discovered we send it to the service to be save. We
        // include a PendingIntent for the service to call back onto. This
        // will cause this activity to be restarted with onNewIntent(). At
        // that time we read it from the database and view it.
       Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
       NdefMessage[] msgs;

       if (rawMsgs != null)
       {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++)
            {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }

            msg1 = msgs[0];
            myPayload=msg1.getRecords()[0].getPayload();
        }
        else {
            // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            msg2 = new NdefMessage(new NdefRecord[] {record});
            msgs = new NdefMessage[] {msg2};
        }
        writeToNfcTag(intent);
    }


    public NdefRecord createRecord() throws UnsupportedEncodingException {
        SharedPreferences prefs = getSharedPreferences(prefName, MODE_PRIVATE);
        mEditText.setText(prefs.getString(TEXT_VALUE_KEY, "def"))

        String lang       = "en";

        byte[] textBytes  = mEditText.getText().toString().getBytes();

        byte[] langBytes  = lang.getBytes("US-ASCII");
        int    langLength = langBytes.length;
        //int    myPayloadLength = myPayload.length;
        int    textLength = textBytes.length;
        byte[] payload    = new byte[1+langLength+textLength];

        // Set status byte (see NDEF spec for actual bits)
        payload[0] = (byte) langLength;

        // Copy langbytes and textbytes into payload
        System.arraycopy(langBytes, 0, payload, 1, langLength);
        System.arraycopy(textBytes, 0, payload, 1+langLength, textLength);
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                                           NdefRecord.RTD_TEXT,
                                           new byte[0],
                                           payload);
        return record;
    }


    public void writeToNfcTag(Intent intent)
    {
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        try
        {
            write(tag);
        }
        catch (Exception e)
        {
            // Toast this; bail
        }
    }


    public void write(Tag tag) throws IOException, FormatException {
        NdefRecord[] records = { mRecord };
        NdefMessage  message = new NdefMessage(records);

        // Get an instance of Ndef for the tag.
        Ndef ndef = Ndef.get(tag);

        // Enable I/O
        ndef.connect();

        // Write the message
        ndef.writeNdefMessage(message);

        // Close the connection
        ndef.close();

        Intent myIntent = null;
        myIntent = new Intent(MyAndroidAppActivity.this, TagDeactivatedActivity.class);

        myIntent.setFlags(myIntent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(myIntent);
        finish();
    }
}

回答1:


After you write in the tag you can do this but keep in mind that this process is not reversible.

    Ndef ndef = Ndef.get(tag);  
    if (ndef != null) { 
        ndef.makeReadOnly();
    }



回答2:


Yes, it is possible to make an activity read and write into tag only once. I solved my problem by declaring a flag as a global variable and used the flag to control my tag reading and writing.

IN your class declare a flag as Boolean. suppose :

public class YourClass{
Boolean flag= false;
.
.
.
.
void resolveIntent(Intent intent)
{
    NdefMessage msg1, msg2;
// Parse the intent
    String action = intent.getAction();
if(flag== false){
flag = true;
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) ||
        NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

        try
        {
            mRecord=createRecord();
        }
        catch (Exception e)
        {
            Toast toaste = Toast.makeText(getApplicationContext(), 
"exception in call to create record", Toast.LENGTH_SHORT);
            toaste.show();
        }

        // When a tag is discovered we send it to the service to be save. We
        // include a PendingIntent for the service to call back onto. This
        // will cause this activity to be restarted with onNewIntent(). At
        // that time we read it from the database and view it.
       Parcelable[] rawMsgs = 
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
       NdefMessage[] msgs;

       if (rawMsgs != null)
       {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++)
            {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }

            msg1 = msgs[0];
            myPayload=msg1.getRecords()[0].getPayload();
        } 
        else {
            // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, 
empty, empty, empty);
            msg2 = new NdefMessage(new NdefRecord[] {record});
            msgs = new NdefMessage[] {msg2};
        }
        writeToNfcTag(intent);
       }
    }
.
.
.
.
}

Hope it helps.



来源:https://stackoverflow.com/questions/12149318/how-to-stop-overwrite-to-an-nfc-tag-using-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!