简体   繁体   中英

Not Reading Nfc 4K Card details in Android

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);
}
}

Follow this tutorial for more info

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM