在 Android 5.1 中无法通过 NFC 读取 Mifare Classic 卡
Can not read Mifare Classic cards through NFC in Android 5.1
我正在使用 NFC 读取 Mifare Classic 1K 卡。
该代码适用于 Android 5.0 及以下版本的所有 Android 设备,但是当我在 Android 5.1 的设备上测试我的代码时,它不起作用。
我已经在 Nexus 7(4.4、5.0)、Nexus 5(5.0)、索尼 Xperia 和三星设备上测试了我的代码,并且运行良好。
但是当 Android 从 5.0 升级到 5.1 时,在某些新设备(Nexus 6、Moto x Play)中我的程序无法运行。
我的代码,
MifareClassic mfc = MifareClassic.get(tagFromIntent);
returns null
当我在 Android 5.1 中扫描我的卡时,否则在 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;
}
部分 NFC 芯片不支持 Mifare Classic 卡。请参阅此 hasMifareClassic() 方法。
您遇到的问题可能与升级到 Android 5.1 无关。相反,为标签获取 MifareClassic
对象的实例仅适用于支持 MIFARE Classic 的平台。因此,
MifareClassic.get(tagFromIntent)
将在不支持 MIFARE Classic 的平台上 return null
。这实质上意味着您的应用只能在配备 NXP NFC 芯片组的设备上运行。
- 对于 Nexus 7,只有 2012 版本支持 MIFARE Classic。 2013版本(Broadcom芯片)将无法读取MIFARE Classic
- Nexus 5 将无法从 MIFARE Classic 读取数据。
- 大多数(全部?)Sony Xperia 应该可以正常工作。
- Samsung 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 的设备的可靠方法。
我正在使用 NFC 读取 Mifare Classic 1K 卡。
该代码适用于 Android 5.0 及以下版本的所有 Android 设备,但是当我在 Android 5.1 的设备上测试我的代码时,它不起作用。
我已经在 Nexus 7(4.4、5.0)、Nexus 5(5.0)、索尼 Xperia 和三星设备上测试了我的代码,并且运行良好。
但是当 Android 从 5.0 升级到 5.1 时,在某些新设备(Nexus 6、Moto x Play)中我的程序无法运行。
我的代码,
MifareClassic mfc = MifareClassic.get(tagFromIntent);
returns null
当我在 Android 5.1 中扫描我的卡时,否则在 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;
}
部分 NFC 芯片不支持 Mifare Classic 卡。请参阅此 hasMifareClassic() 方法。
您遇到的问题可能与升级到 Android 5.1 无关。相反,为标签获取 MifareClassic
对象的实例仅适用于支持 MIFARE Classic 的平台。因此,
MifareClassic.get(tagFromIntent)
将在不支持 MIFARE Classic 的平台上 return null
。这实质上意味着您的应用只能在配备 NXP NFC 芯片组的设备上运行。
- 对于 Nexus 7,只有 2012 版本支持 MIFARE Classic。 2013版本(Broadcom芯片)将无法读取MIFARE Classic
- Nexus 5 将无法从 MIFARE Classic 读取数据。
- 大多数(全部?)Sony Xperia 应该可以正常工作。
- Samsung 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 的设备的可靠方法。