Android & NFC howto
When a NFC tag is discovered, the system checks if the foreground application has registered to such an Intent with a call to enableForegroundDispatch(). If not, it checks whether any other applications has registered for the NDEF_DISCOVERED intent. If an application want to register for events related to a tag of a specific technology (e.g. classic MiFare tags) then it should register to the TECH_DISCOVERED intent.The following diagram explains in details how an event related to reading a tag is handled:
Read NFC tag in Android
Declare in the manifest a specific Activity to receive an Intent when a NFC tag is read by the device:<activity android:name=".NfcReaderActivity" android:label="NfcReaderActivity">
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
To register the foreground Activity for tag reading events, add following lines to onResume() method:
@Override protected onResume() { PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); mAdapter.enableForegroundDispatch(this, pendingIntent, null, null); }
In the onNewIntent(Intent)to read the tag after receiving a ACTION_TAG_DISCOVERED intent :
protected void onNewIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)){ Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage[] messages; if (rawMsgs != null) { messages = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { messages[i] = (NdefMessage) rawMsgs[i]; // To get a NdefRecord and its different properties from a NdefMesssage NdefRecord record = messages[i].getRecords()[i]; byte[] id = record.getId(); short tnf = record.getTnf(); byte[] type = record.getType(); String message = getTextData(record.getPayload()); } } } }
This is how to read the content tag of type text RTD_TEXT:
// Decoding a payload containing text private String getTextData(byte[] payload) { if(payload == null) return null; try { String encoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16"; int langageCodeLength = payload[0] & 0077; return new String(payload, langageCodeLength + 1, payload.length - langageCodeLength - 1, encoding); } catch(Exception e) { e.printStackTrace(); } return null; }
Write NFC tag in Android
In the manifest:<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />in onCreate() get the NfcAdapter:
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);The data part of a TAG is a NdefMessage of multiple NdefRecord this is how to encode a text into a payload:
// Encoding a text into a tag payload NdefRecord createRecord(String message) { byte[] langBytes = Locale.ENGLISH.getLanguage().getBytes(Charset.forName("US-ASCII")); byte[] textBytes = message.getBytes(Charset.forName("UTF-8")); char status = (char) (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); return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); } // Create a message from a record NdefMessage createMessage(NdefRecord record) { NdefRecord[] records = new NdefRecord[1]; records[0] = record; NdefMessage message = new NdefMessage(records); return message; }To enable/disable sending a message each time a tag is read
@Override protected void onPause() { super.onPause(); nfcAdapter.disableForegroundNdefPush(this); } @Override protected void onResume() { super.onResume(); NdefRecord record = creerRecord("this is a message"); NdefMessage message = creerMessage(record); nfcAdapter.enableForegroundNdefPush(this, message); }If there is no tag, we can simulate a tag been read by sending the corresponding intent, this is how:
final Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED); NdefMessage[] messages = new NdefMessage[1]; messages[0] = createMessage(createRecord("Simulating a tag reception")); intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, messages); startActivity(intent);
Reference Programming Android, chapter 16: Sensors, NFC, Speech, Gestures, and Accessibility.
I actually enjoyed reading through this posting.Many thanks.Good article! We are linking to this great article on our site. Keep up the good writing.
RépondreSupprimerwebsite design