Как записать записи NDEF в тег NFC?

Как мне записать сообщение NDEF в тег NFC? Мне нужно изменить файл манифеста? Пока у меня есть код для создания сообщения 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;
}

Как мне узнать ТЕГ? Кто-нибудь может мне с этим помочь?


person Camil    schedule 19.11.2020    source источник


Ответы (1)


Я бы проигнорировал то, что говорится в документации Google, для чтения на https://developer.android.com/guide/topics/connectivity/nfc/nfc и для чтения / записи на https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc#read.-write, так как это очень затрудняет запись на Теги и приводят к множеству неудачных операций записи из-за поведения пользователя.

Чтобы обеспечить надежную запись в NFC с Android, вам следует использовать более новый и гораздо лучший enableReaderMode API https://developer.android.com/reference/android/nfc/NfcAdapter

Использование этого нового API приводит к гораздо меньшему количеству сбоев записи и поврежденных карт, поскольку вы можете контролировать, когда происходит звук уведомления. В старой системе, основанной на Intent, системное приложение приостанавливает ваше приложение, а затем считывает карту и издает звук уведомления, затем пользователь берет карту, прежде чем ваше приложение будет возобновлено, и имеет возможность обработать данные карты и записать на карту.

С новым enableReaderMode API вы отключаете звук системного уведомления, и ваше приложение никогда не приостанавливается для чтения карты NFC, затем вы можете читать и записывать на карту, а затем, когда вы успешно записали на карту, вы можете сделать звук уведомления самостоятельно .

Поскольку любые ошибки не отображаются, пользователь будет продолжать попытки предъявить карту до получения уведомления об успешном завершении. Требуется дополнительная логика, чтобы не писать одно и то же сообщение каждый раз, когда предъявляется одна карточка или когда представляются разные карточки.

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


public class NFCActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback{

private NfcAdapter mNfcAdapter;

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

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // Rest of Activity setup
     }

@Override
    protected void onResume() {
        super.onResume();

        if(mNfcAdapter!= null) {
            Bundle options = new Bundle();
            // Work around for some broken Nfc firmware implementations that poll the card too fast
            options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);

            // Enable ReaderMode for all types of card and disable platform sounds
            mNfcAdapter.enableReaderMode(this,
                    this,
                    NfcAdapter.FLAG_READER_NFC_A |
                            NfcAdapter.FLAG_READER_NFC_B |
                            NfcAdapter.FLAG_READER_NFC_F |
                            NfcAdapter.FLAG_READER_NFC_V |
                            NfcAdapter.FLAG_READER_NFC_BARCODE |
                            NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
                    options);
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mNfcAdapter!= null)
            mNfcAdapter.disableReaderMode(this);
    }
    
   // This method is run in another thread when a card is discovered
   // !!!! This method cannot cannot direct interact with the UI Thread
   // Use `runOnUiThread` method to change the UI from this method
   public void onTagDiscovered(Tag tag) {

      // Read and or write to Tag here to the appropriate Tag Technology type class
      // in this example the card should be an Ndef Technology Type 
      Ndef mNdef = Ndef.get(tag);

      // Check that it is an Ndef capable card
      if (mNdef!= null) {

      // If we want to read
      // As we did not turn on the NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK
      // We can get the cached Ndef message the system read for us.

      NdefMessage mNdefMessage = mNdef.getCachedNdefMessage();


      // Or if we want to write a Ndef message

      // Create a Ndef Record
      NdefRecord mRecord = NdefRecord.createTextRecord("en","English String");

      // Add to a NdefMessage
      NdefMessage mMsg = new NdefMessage(mRecord);
      
      // Catch errors
      try {
          mNdef.connect();
          mNdef.writeNdefMessage(mMsg);

          // Success if got to here
          runOnUiThread(() -> {
             Toast.makeText(getApplicationContext(),
               "Write to NFC Success",
               Toast.LENGTH_SHORT).show();
          });

          // Make a Sound
          try {
              Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
              Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),
                  notification);
              r.play();
              } catch (Exception e) {
                 // Some error playing sound
              }
          
      } catch (FormatException e) {
        // if the NDEF Message to write is malformed
      } catch (TagLostException e) {
        // Tag went out of range before operations were complete
      } catch (IOException e){
        // if there is an I/O failure, or the operation is cancelled
      } finally {
        // Be nice and try and close the tag to
        // Disable I/O operations to the tag from this TagTechnology object, and release resources. 
         try {
                mNdef.close();
             } catch (IOException e) {
               // if there is an I/O failure, or the operation is cancelled
             }
      }

   }

}

person Andrew    schedule 19.11.2020
comment
Я получаю сообщение об ошибке в строке mNdef.writeNdefMessage (mMsg); Ошибка: W / Binder: обнаружено исключение RuntimeException из реализации заглушки связующего. java.lang.IllegalStateException: сначала вызовите connect ()! - person Camil; 21.11.2020
comment
Извините, я забыл передать это при адаптации моего кода Nfca к технологии тегов Ndef, пример обновлен с mNdef.connect(); непосредственно перед mNdef.writeNdefMessage(mMsg); - person Andrew; 21.11.2020