package nordpol.android; import android.nfc.Tag; import android.nfc.NfcAdapter; import android.nfc.tech.IsoDep; import android.annotation.TargetApi; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.content.IntentFilter; import android.os.Build; import android.os.Bundle; public class TagDispatcher { private OnDiscoveredTagListener listener; private Activity activity; private TagDispatcher(Activity activity, OnDiscoveredTagListener listener) { this.activity = activity; this.listener = listener; } public static TagDispatcher get(Activity activity, OnDiscoveredTagListener listener) { return new TagDispatcher(activity, listener); } /** Enable exclusive NFC access for the given activity. * @returns true if NFC was available and false if no NFC is available * on device. */ @TargetApi(Build.VERSION_CODES.KITKAT) public boolean enableExclusiveNfc() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity); if (adapter != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { enableReaderMode(adapter); } else { enableForegroundDispatch(adapter); } return true; } return false; } /** Disable exclusive NFC access for the given activity. * @returns true if NFC was available and false if no NFC is available * on device. */ @TargetApi(Build.VERSION_CODES.KITKAT) public boolean disableExclusiveNfc() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity); if (adapter != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { disableReaderMode(adapter); } else { disableForegroundDispatch(adapter); } return true; } return false; } public boolean interceptIntent(Intent intent) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if(tag != null) { listener.tagDiscovered(tag); return true; } else { return false; } } private void enableReaderMode(NfcAdapter adapter) { Bundle options = new Bundle(); /* This is a work around for some Broadcom chipsets that does * the presence check by sending commands that interrupt the * processing of the ongoing command. */ //options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 5000); options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 30000); NfcAdapter.ReaderCallback callback = new NfcAdapter.ReaderCallback() { public void onTagDiscovered(Tag tag) { listener.tagDiscovered(tag); } }; adapter.enableReaderMode(activity, callback, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS, options); } private void disableReaderMode(NfcAdapter adapter) { adapter.disableReaderMode(activity); } private void enableForegroundDispatch(NfcAdapter adapter) { // activity.getIntent() can not be use due to issues with pending intents containg extras of custom classes (https://code.google.com/p/android/issues/detail?id=6822) Intent intent = new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); enableForegroundDispatch(adapter, intent); } private void enableForegroundDispatch(NfcAdapter adapter, Intent intent) { if(adapter.isEnabled()) { PendingIntent tagIntent = PendingIntent.getActivity(activity, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); IntentFilter tag = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); adapter.enableForegroundDispatch(activity, tagIntent, new IntentFilter[]{tag}, new String[][]{new String[]{IsoDep.class.getName()}}); } } private void disableForegroundDispatch(NfcAdapter adapter) { adapter.disableForegroundDispatch(activity); } }