如何将NDEF记录写入NFC标签?
How to write NDEF records to NFC tag?
如何将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;
}
如何发现 TAG?
有人可以帮我吗?
我会忽略 Google 文档在 https://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 上阅读的内容,因为这为写入标签提供了非常糟糕的用户体验,并且由于用户行为导致大量写入失败。
要使用 Android 可靠地写入 NFC,您应该使用更新更好的 enableReaderMode
API https://developer.android.com/reference/android/nfc/NfcAdapter
使用这个较新的 API 可以大大减少写入失败和卡损坏,因为您可以控制何时发出通知声音。使用基于旧 Intent
的系统,系统 App 会暂停您的应用程序,然后读取卡片并发出通知声音,然后用户在您的应用程序恢复之前取走卡片,并有机会处理卡片数据并写入到卡片。
使用较新的enableReaderMode
API您关闭系统通知声音并且您的应用程序永远不会暂停读取NFC卡,然后您可以读取和写入卡然后当您写卡成功可以自己发出提示音了
因为任何错误都是无声的,所以用户会一直尝试出示卡,直到成功通知。需要额外的逻辑来避免每次出示一张卡片或出示不同的卡片时写入相同的消息。
一些示例代码(改编自我的应用程序 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
}
}
}
}
如何将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;
}
如何发现 TAG? 有人可以帮我吗?
我会忽略 Google 文档在 https://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 上阅读的内容,因为这为写入标签提供了非常糟糕的用户体验,并且由于用户行为导致大量写入失败。
要使用 Android 可靠地写入 NFC,您应该使用更新更好的 enableReaderMode
API https://developer.android.com/reference/android/nfc/NfcAdapter
使用这个较新的 API 可以大大减少写入失败和卡损坏,因为您可以控制何时发出通知声音。使用基于旧 Intent
的系统,系统 App 会暂停您的应用程序,然后读取卡片并发出通知声音,然后用户在您的应用程序恢复之前取走卡片,并有机会处理卡片数据并写入到卡片。
使用较新的enableReaderMode
API您关闭系统通知声音并且您的应用程序永远不会暂停读取NFC卡,然后您可以读取和写入卡然后当您写卡成功可以自己发出提示音了
因为任何错误都是无声的,所以用户会一直尝试出示卡,直到成功通知。需要额外的逻辑来避免每次出示一张卡片或出示不同的卡片时写入相同的消息。
一些示例代码(改编自我的应用程序 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
}
}
}
}