You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android NFC读取记录时获取到Null Ndef Record问题求助

Troubleshooting Your Mifare Card NDEF Reading Issue

Hey there! Let's break down why you're seeing a null Ndef instance and can't read the records you wrote with Nfc Tools. Here are the most likely issues and fixes:

1. Mifare Classic Cards Lack Native NDEF Support

First off, if you're using a Mifare Classic 1K/4K card (the most common type), these don't have built-in NDEF support. When you write NDEF data to them with tools like Nfc Tools, the app emulates the NDEF structure by storing data in specific Mifare blocks. That's exactly why Ndef.get(detectedTag) returns null—this method only works with tags that have native NDEF support (like Mifare Ultralight or NTAG213).

2. Your Intent Filter Is Too Restrictive

Right now, your readNfcTag method only triggers when the intent action is ACTION_NDEF_DISCOVERED. But for Mifare Classic cards, the system usually sends ACTION_TECH_DISCOVERED or ACTION_TAG_DISCOVERED instead. That means your code never even gets a chance to process the tag's data.

3. Fixed Code with Multi-Tag Support

Let's adjust your code to handle both native NDEF tags and Mifare Classic cards, plus fix small bugs like uninitialized variables and silent exception swallowing:

Updated MainActivity Code

import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {
    private TextView mNfcText;
    private String mTagText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mNfcText = findViewById(R.id.textME);
        mTagText = ""; // Initialize to avoid null concatenation issues
    }

    @Override
    public void onNewIntent(android.content.Intent intent) {
        super.onNewIntent(intent);
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        mTagText = ""; // Reset text for each new scan

        // Check for native NDEF support first
        Ndef ndef = Ndef.get(detectedTag);
        if (ndef != null) {
            mTagText += "Native NDEF Tag Detected\n";
            readNativeNdef(intent);
        } else {
            // Check if it's a Mifare Classic card
            boolean isMifareClassic = Arrays.asList(detectedTag.getTechList())
                    .contains(MifareClassic.class.getName());
            if (isMifareClassic) {
                mTagText += "Mifare Classic Card Detected\n";
                readMifareClassic(detectedTag);
            } else {
                mTagText += "Unsupported Tag Type\n";
            }
        }

        mNfcText.setText(mTagText);
    }

    // Handle tags with native NDEF support
    private void readNativeNdef(android.content.Intent intent) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs == null) {
            mTagText += "No NDEF messages found\n";
            return;
        }

        NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
        for (int i = 0; i < rawMsgs.length; i++) {
            msgs[i] = (NdefMessage) rawMsgs[i];
        }

        try {
            NdefRecord record = msgs[0].getRecords()[0];
            String text = parseTextRecord(record);
            if (text != null) {
                mTagText += "Read Text: " + text + "\n";
            } else {
                mTagText += "Could not parse text record\n";
            }
        } catch (Exception e) {
            mTagText += "Error reading NDEF: " + e.getMessage() + "\n";
            e.printStackTrace();
        }
    }

    // Handle Mifare Classic cards with emulated NDEF
    private void readMifareClassic(Tag tag) {
        MifareClassic mifare = MifareClassic.get(tag);
        try {
            mifare.connect();
            // Nfc Tools usually writes emulated NDEF to sector 1 (blocks 4-7) for 1K cards
            int sector = 1;
            // Use default key (Nfc Tools often uses this for unprotected sectors)
            if (mifare.authenticateSectorWithKeyA(sector, MifareClassic.KEY_DEFAULT)) {
                int startBlock = mifare.sectorToBlock(sector);
                byte[] blockData = mifare.readBlock(startBlock);
                mTagText += "Sector 1 Block Data: " + bytesToHex(blockData) + "\n";
                // For full emulated NDEF parsing, you'd need to read all blocks in the sector
                // and reconstruct the NDEF message structure
            } else {
                mTagText += "Authentication failed for sector 1\n";
            }
            mifare.close();
        } catch (IOException e) {
            mTagText += "Error reading Mifare Classic: " + e.getMessage() + "\n";
            e.printStackTrace();
        }
    }

    // Your text record parser with better error handling
    public static String parseTextRecord(NdefRecord ndefRecord) {
        if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) {
            return null;
        }
        if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
            return null;
        }
        try {
            byte[] payload = ndefRecord.getPayload();
            String encoding = ((payload[0] & 0x80) == 0) ? StandardCharsets.UTF_8.name() : StandardCharsets.UTF_16.name();
            int langCodeLength = payload[0] & 0x3f;
            return new String(payload, langCodeLength + 1, payload.length - langCodeLength - 1, encoding);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // Helper to convert bytes to hex for debugging
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}

Key Improvements:

  • Initialized mTagText to avoid weird null string concatenation results.
  • Multi-tag support: Checks for native NDEF first, then falls back to Mifare Classic handling.
  • Mifare Classic logic: Uses the MifareClassic class to connect, authenticate, and read blocks (uses the default key Nfc Tools often uses).
  • Better error visibility: Catches and displays exceptions instead of hiding them, so you can debug exactly what's failing.
  • Broader intent handling: Processes all tag discovery intents, not just ACTION_NDEF_DISCOVERED.

Quick Tips:

  • Verify your card type: Mifare Ultralight supports native NDEF, so your original code would work for those.
  • If Nfc Tools used a custom key to write the card, replace MifareClassic.KEY_DEFAULT with that key (common alternatives are KEY_MIFARE_APPLICATION_DIRECTORY or custom hex keys).
  • For full emulated NDEF parsing on Mifare Classic, you'll need to read all blocks in the sector and reconstruct the NDEF message—this example starts with the first block of sector 1 as a debugging step.

内容的提问来源于stack exchange,提问作者Ousmane Elhadji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:58:10