I want to read NFC 4K card details, Its not reading the data, Here is the Code I use,
AndroidManifest.xml
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />
</activity>
nfc_tech_filter.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
MainActivity.java
public class MainActivity extends Activity implements NfcAdapter.ReaderCallback {
public static final String TAG = " --NFC-- " + MainActivity.class.getSimpleName();
private NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
showToast("No NFC found...");
} else {
showToast("NFC Enables Device...");
enableReaderMode();
}
}
@Override
public void onResume() {
super.onResume();
showToast("On Resume...");
enableReaderMode();
}
@Override
protected void onPause() {
super.onPause();
showToast("On Pause...");
disableReaderMode();
}
private void showToast(String message) {
Log.d(TAG, message);
try {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
showToast("Show Toast Exception : " + message);
}
}
private void enableReaderMode() {
showToast("Enabling reader mode...");
Activity activity = MainActivity.this;
nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (nfcAdapter != null) {
nfcAdapter.enableReaderMode(activity, this, Integer.MAX_VALUE, null);
}
}
private void disableReaderMode() {
showToast("Disabling reader mode...");
Activity activity = MainActivity.this;
nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (nfcAdapter != null)
nfcAdapter.disableReaderMode(activity);
}
@Override
public void onTagDiscovered(Tag tag) {
Log.d(TAG, "New tag discovered...");
}
@Override
protected void onNewIntent(Intent intent) {
Log.d(TAG, "New Intent...");
super.onNewIntent(intent);
}
}
Your are not handling your intent data in onNewIntent(). onNewIntent() will be call whenever you scan your NFC card. Like below example:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "New Intent...");
handleIntent(intent);
}
private void handleIntent(Intent intent) {
val bundle = intent.extras
if (bundle != null) {
Log.e(TAG,intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
}
}
Edited
You need to call this method from onResume() after adding adapter.
private fun setupForegroundDispatch(activity : Activity, adapter
: NfcAdapter) {
val intent = Intent(activity.applicationContext,
activity.javaClass)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
val pendingIntent =
PendingIntent.getActivity(activity.applicationContext, 0,
intent, 0)
// val filters = arrayOfNulls<IntentFilter>(1)
// val techList = arrayOf<Array<String>>()
val ndef = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
val filters = arrayOf(ndef)
// val techList = arrayOf<Array<String>>()
val techList = arrayOf(arrayOf(NfcV::class.java.name))
// Notice that this is the same filter as in our manifest.
filters[0] = IntentFilter()
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED)
filters[0].addCategory(Intent.CATEGORY_DEFAULT)
try {
filters[0].addDataType(MIME_TEXT_PLAIN)
}
catch (e : IntentFilter.MalformedMimeTypeException) {
throw RuntimeException("Check your mime type.")
}
adapter.enableForegroundDispatch(activity, pendingIntent,
filters, techList)
}
Like below:
private void enableReaderMode() {
showToast("Enabling reader mode...");
Activity activity = MainActivity.this;
nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (nfcAdapter != null) {
nfcAdapter.enableReaderMode(activity, this,
Integer.MAX_VALUE, null);
setupForegroundDispatch(this,nfcAdapter);
}
}
As you are using enableReaderMode
you don't need the onNewIntent
method.
Also the intent-filter
in the manifest and nfc_tech_filter.xml might not be required (They are not need if you don't want your app to be started by an NFC Tag if not running, then you would handle the NFC Intent in onCreate
)
What you have not done is setup enableReaderMode
correctly.
@Override
protected void onResume() {
super.onResume();
if(nfcAdapter!= null) {
Bundle options = new Bundle();
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
nfcAdapter.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);
}
}
Turning off NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS
is optional if you want to generate your own notification of reading instead of the OS doing it.
Note that the newer NFC API of enableReaderMode
gives you more control that the older enableForegroundDispatch
and is much more reliable than enableForegroundDispatch
when writing to NFC Tags and it does not have some of the Negative side effects of enableForegroundDispatch
, so I would recommend to always use enableReaderMode
unless you want to support really old API's
Also note that using Mifare 4K cards is not recommended as well as they are a proprietary format and not supported by all Android Hardware (not matter which API you use)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.