Reputation: 39
My current Android application recognises any NFC tag and performs the required function. However, I want it to only work with a specific tag with a specific UID. What is the best way to accomplish this?
The UID for the tag in question is: 046a0b42402b84
My code for the NFC function is below:
public class NFC extends AppCompatActivity {
NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nfc);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
String username = getIntent().getStringExtra("Username");
TextView tv = (TextView) findViewById(R.id.TVusername);
tv.setText(username);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(nfcAdapter!=null && nfcAdapter.isEnabled()) {
}else{
finish();
}
}
@Override
protected void onNewIntent(Intent intent) {
Toast.makeText(this, "NFC intent received!", Toast.LENGTH_LONG).show();
super.onNewIntent(intent);
}
@Override
protected void onResume() {
Intent intent = new Intent(this, AttendanceRegistration.class);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
IntentFilter[] intentFilter = new IntentFilter[]{};
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilter, null);
super.onResume();
}
@Override
protected void onPause() {
nfcAdapter.disableForegroundDispatch(this);
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Upvotes: 1
Views: 366
Reputation: 40821
Android does not allow NFC tag detection notifications to be registered for specific tags by their UID/anti-collision identifier/serial number. If you want your app to be started only by a specific NFC tag (through registration of an intent filter in ANdroidManifest.xml), you would need to store an NDEF message (containing a custom NDEF record that you can filter on or and Android Application Record) on the tag
If you do not want your application to get launched by the tag and only want to detect the tag while your activity is in the foreground (your code already tries to do this by registering for the foreground dispatch system), you can receive notifications for all discovered tags and simply filter the tags based on their UID.
First, you need to properly register for the foreground dispatch system to receive notifications for any tag (note that you cannot register the foreground dispatch with a PendingIntent for another activity!):
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
You can then receive the NFC discovery intents in onNewIntent
and filter them based on the tag UID:
@Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()) ||
NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] uid = tag.getId();
byte[] referenceUid = new byte[]{ (byte)0x04, (byte)0x6a, (byte)0x0b, (byte)0x42, (byte)0x40, (byte)0x2b, (byte)0x84 };
if (Arrays.equals(referenceUid, uid)) {
// do something
}
}
}
Upvotes: 1