在Android 5.1中无法通过NFC读取Mifare Classic卡

时间:2015-09-22 04:29:42

标签: android nullpointerexception nfc rfid mifare

我正在使用NFC阅读Mifare Classic 1K卡。

该代码适用于Android 5.0及更低版本的所有Android设备,但当我在使用Android 5.1的设备上测试我的代码时,它无效。

我已经在Nexus 7(4.4,5.0),Nexus 5(5.0),Sony Xperia和Samsung设备上测试了我的代码,它运行得非常好。

但是当Android从5.0升级到5.1时,在某些新设备(Nexus 6,Moto x Play)中,我的程序无效。

我的代码,

MifareClassic mfc = MifareClassic.get(tagFromIntent);
当我在Android 5.1中扫描我的卡时,

返回null,否则在5.1以下的版本中,它会正常工作。

代码:

@SuppressLint("InlinedApi")
public String AuthenticateCard(Context context, Intent nfcIntent) {
    String blockData = null;

    //Get an instance of the TAG from the NfcAdapter
    Tag tagFromIntent = nfcIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    String idFromIntent = ByteArrayToHexString(tagFromIntent.getId());

    Log.v("onNewIntent()", "NfcAdapter TAG : " + tagFromIntent
            + "NfcAdapter ID : " + idFromIntent);

    Log.v("onNewIntent()", "TAG TYPE : " + tagFromIntent.describeContents());

    //Get an instance of the Mifare classic card from this TAG intent

    //It works successfully with android 5.0 or below versions but returns null in devices with android 5.1.
    MifareClassic mfc = MifareClassic.get(tagFromIntent);


    try {
        // Connect to card
        mfc.connect();
         // authenticate the sector
        if (mfc.authenticateSectorWithKeyA(MY_SECTOR, MY_KEY)) {

            for (int k = 0; k < 1; ++k) {
                int block = mfc.sectorToBlock(MY_SECTOR) + k;
                byte[] data = null;

                try {
                     // Read the block
                    data = mfc.readBlock(block);
                } catch (IOException e) {
                    Log.e("IOException", "\n" + "Block " + block
                            + " data: " + e.getMessage());
                    continue;
                }
                 // Convert the data into a string from Hex format.
                blockData = ByteArrayToHexString(data);

                // reading first 8 bytes only
                blockData = blockData.substring(0, 8);
            }

            if (blockData != null) {
                mp = MediaPlayer.create(context, R.raw.served);
            } else {
                mp = MediaPlayer.create(context, R.raw.coins);
            }

        } else {
            Toast.makeText(context, R.string.not_valid_rfid,
                    Toast.LENGTH_SHORT).show();
            mp = MediaPlayer.create(context, R.raw.professionals);
        }

        mfc.close();

    } catch (IOException e) {
        mp = MediaPlayer.create(context, R.raw.coins);
        Toast.makeText(context, R.string.error_while_scanning,
                Toast.LENGTH_SHORT).show();
    } catch (NullPointerException e) {
        // TODO: handle exception
        mp = MediaPlayer.create(context, R.raw.coins);
        Toast.makeText(context, R.string.error_while_scanning,
                Toast.LENGTH_SHORT).show();
    }finally {
        try {
            if (mfc != null)
                mfc.close();
            if (mp != null)
                mp.start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return blockData;
}

2 个答案:

答案 0 :(得分:4)

某些NFC芯片不支持Mifare Classic卡。请参阅此hasMifareClassic()方法。

答案 1 :(得分:3)

您遇到的问题可能与升级到Android 5.1无关。相反,为标记获取MifareClassic对象的实例仅适用于支持MIFARE Classic的平台。因此,

MifareClassic.get(tagFromIntent)

将在不支持MIFARE Classic的平台上返回null。这实际上意味着您的应用只适用于恩智浦NFC芯片组的设备。

  • 对于Nexus 7,只有2012版本才支持MIFARE Classic。 2013版(Broadcom芯片)将无法阅读MIFARE Classic。
  • Nexus 5将无法从MIFARE Classic中读取数据。
  • 大多数(全部?)Sony Xperia应该可以正常工作。
  • 三星Galaxy S4(可能还有Note 3和Note 4)将无法从MIFARE Classic读取数据。 S3和S5工作正常。
  • Nexus 6具有Broadcom NFC芯片,因此无法从MIFARE Classic读取数据。

请注意,系统功能com.nxp.mifare应该表明设备是否支持MIFARE Classic(请参阅ThomasRS的回答)。但是,许多供应商都没有费心去正确配置它。因此,使用

if (getPackageManager().hasSystemFeature("com.nxp.mifare")) { ... }

不是识别支持MIFARE Classic的设备的非常可靠的方法。