简体   繁体   English

如何将 NDEF 记录写入 NFC 标签?

[英]How to write NDEF records to NFC tag?

How do I write NDEF message to NFC tag?如何将 NDEF 消息写入 NFC 标签? Do I have to change manifest file?我必须更改清单文件吗? So far I have code to generate NDEF message:到目前为止,我有代码来生成 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;
}

How do I discover the TAG?我如何发现 TAG? Can someone help me with that?有人可以帮我吗?

I would ignore what the Google documentation says for reading athttps://developer.android.com/guide/topics/connectivity/nfc/nfc and for read/write at https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc#read-write as this provides a very poor user experience for writing to Tags and leads to a lot of failed writes because of user behaviour.我会忽略什么谷歌文件说,在阅读https://developer.android.com/guide/topics/connectivity/nfc/nfc和在读/写https://developer.android.com/guide/topics/连接/nfc/advanced-nfc#read-write因为这为写入标签提供了非常差的用户体验,并由于用户行为导致大量写入失败。

To get reliable writing to NFC with Android you should use the newer and much better enableReaderMode API https://developer.android.com/reference/android/nfc/NfcAdapter要使用 Android 可靠地写入 NFC,您应该使用更新更好的enableReaderMode API https://developer.android.com/reference/android/nfc/NfcAdapter

Using this newer API leads to a lot less failed writes and corrupted cards because you can control when the notification sound happens.使用这个较新的 API 会导致写入失败和卡损坏的情况减少很多,因为您可以控制通知声音何时发生。 With the old Intent based system the system App pauses your app and then reads the card and makes a notification sound, the user then takes the card way before your App is resumed and has a chance to handle the card data and write to the card.在旧的基于Intent的系统中,系统 App 会暂停您的应用程序,然后读取卡并发出通知声音,然后用户在您的应用程序恢复之前采用卡方式,并有机会处理卡数据并写入卡。

With the newer enableReaderMode API you turn off the system notification sound and your App is never paused to read the NFC card, you can then read and write to the card and then when you have successfully written to the card you can make the notification sound yourself.使用较新的enableReaderMode API,您可以关闭系统通知声音并且您的应用程序永远不会暂停读取 NFC 卡,然后您可以读写卡,然后当您成功写入卡​​时,您可以自己发出通知声音.

Because any errors are silent, the user will keep trying to present the card until the success Notification.因为任何错误都是无声的,用户将不断尝试出示卡片,直到成功通知。 Additional logic is needed not to write the same message to every time a single card is presented or when different cards are presented.需要额外的逻辑来避免每次出示单张牌或出示不同牌时都写入相同的消息。

Some example code (adapted from my app the does NFC low level reading and writing (not Ndef Tag technology))一些示例代码(改编自我的应用程序,NFC 低级读写(不是 Ndef 标签技术))


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
             }
      }

   }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM