Я получаю исключение потерянного тега при попытке записи в тег NFC

Я надеюсь, что кто-то может сказать мне, что я здесь скучаю. Может быть, это мой подход к подключению. My Tag, на самом деле Mifare Ultralight, так что я не ошибаюсь. Я отладил, подключение к тегу прошло успешно - все выглядело нормально. Но журнал продолжает говорить:

android.nfc.TagLostException: тег был потерян.

public class MainActivity extends Activity {

    NfcAdapter mNfcAdapter;
    TextView displayInfo;
    Tag mNfcTag;
    NdefMessage mNdefMessage;

    IntentFilter [] intentFiltersArray;

    String [] [] techListsArray;

    PendingIntent pendingIntent;


    String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        displayInfo = (TextView) findViewById(R.id.displayInfo);

        NdefRecord application = NdefRecord.createApplicationRecord("com.studios.nfcdemo");


        Locale locale = new Locale("en");

        NdefRecord textText = createTextRecord("pleaseWork", locale, true);

        mNdefMessage = new NdefMessage(textText);

        pendingIntent = PendingIntent.getActivity(
                this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");    /* Handles all MIME based dispatches.
                                       You should specify only the ones that you need. */
        }
        catch (IntentFilter.MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }

        intentFiltersArray = new IntentFilter[] {ndef};

        techListsArray = new String[][] { new String[] { MifareUltralight.class.getName() } };




    }
    public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
        byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
        Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
        byte[] textBytes = payload.getBytes(utfEncoding);
        int utfBit = encodeInUtf8 ? 0 : (1 << 7);
        char status = (char) (utfBit + langBytes.length);
        byte[] data = new byte[1 + langBytes.length + textBytes.length];
        data[0] = (byte) status;
        System.arraycopy(langBytes, 0, data, 1, langBytes.length);
        System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_TEXT, new byte[0], data);
        return record;
    }

    @Override
    public void onNewIntent(Intent intent) {
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        MifareUltralight ultralight = MifareUltralight.get(tagFromIntent);
        write(ultralight);
    }


    private void write(MifareUltralight lol) {
        try{
            lol.connect();
            lol.writePage(0, "please work".getBytes(Charset.forName("US-ASCII")));
            Toast.makeText(this, "Tag written", Toast.LENGTH_LONG).show();

        }
        catch (Exception e){
            Log.d(TAG, "no  " + e.toString());
        }
        finally{
            try{
                lol.close();
            }
            catch (Exception e){
                Log.d(TAG, e.toString());
            }
        }
    }

    public void onPause() {
        super.onPause();
        mNfcAdapter.disableForegroundDispatch(this);
    }

    public void onResume() {
        super.onResume();
        mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
    }
}

2 ответа

Решение

Я нашел свою ошибку. Я хотел написать сообщения Ndef, и использовать тег как MifareUltralight было немного глупо, поскольку он только усложнял все. Вместо этого я использую тег как Ndef. Вот мой код:

private void write(Tag tag) {
        Ndef ndef = Ndef.get(tag);
        Locale locale = Locale.ENGLISH;
        NdefRecord hi = createTextRecord("hello world", locale, true);
        mNdefMessage = new NdefMessage(hi);

        try{
            ndef.connect();
            ndef.writeNdefMessage(mNdefMessage);
            Toast.makeText(this, "Message Written", Toast.LENGTH_LONG).show();
        }
        catch (Exception e){
            Log.d(TAG, "Exception:  " + e.toString());
        }
        finally {
            try{
                ndef.close();
            }
            catch(Exception e){
                Log.d(TAG, ":( no  " + e.toString());
            }
        }
    }

На случай, если кому-то понадобится выяснить, как создавать текстовые записи (закодированные в UTF 8) и читать из поддерживаемых Ndef тегов, я также добавил свои методы для них:

Создание текстовых записей:

public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
    byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
    Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
    byte[] textBytes = payload.getBytes(utfEncoding);
    int utfBit = encodeInUtf8 ? 0 : (1 << 7);
    char status = (char) (utfBit + langBytes.length);
    byte[] data = new byte[1 + langBytes.length + textBytes.length];
    data[0] = (byte) status;
    System.arraycopy(langBytes, 0, data, 1, langBytes.length);
    System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
    NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
            NdefRecord.RTD_TEXT, new byte[0], data);
    return record;
}

Чтение тегов NDEF:

private void read(Tag tagFromIntent) {
    Ndef ndef = Ndef.get(tagFromIntent);

    try{
        ndef.connect();
        mNdefMessage = ndef.getNdefMessage();
        NdefRecord [] records = mNdefMessage.getRecords();
        byte [] payload = records[0].getPayload();
        String displayString = getTextFromNdefRecord(records[0]);
        displayInfo.setText(displayString);
        Toast.makeText(this, "String read", Toast.LENGTH_LONG).show();
    }
    catch (Exception e){
        Log.d(TAG, e.toString());
    }
    finally {
        try{
            ndef.close();
        }
        catch (Exception e){
            Log.d(TAG, e.toString());
        }
    }

чтение текста из NdefRecords:

 public String getTextFromNdefRecord(NdefRecord ndefRecord)
{
    String tagContent = null;
    try {
        byte[] payload = ndefRecord.getPayload();
        String textEncoding = "UTF-8";
        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. Эти простые методы должны дать вам всю необходимую вам функциональность в Android.

Есть две проблемы с вашим звонком на writePage() метод:

  1. Страница 0 тегов MIFARE Ultralight доступна только для чтения. Вы не можете написать на эту страницу. То же самое относится к странице 1 и частям страницы 2 (хотя команды записи для страницы два должны быть успешными и установят биты блокировки).

  2. Команда записи занимает 4 байта (ровно 4 байта, не больше и не меньше), но вы пытаетесь передать 11 байтов ("пожалуйста, работайте" в US-ASCII).

Другие вопросы по тегам