如何在Android上通过NFC向M1卡发送7位指令?
How to send 7 bit commands to M1 card by NFC on Android?
我在 Android 上使用 NFC 时遇到问题。我想向 M1 卡发送一些数据。我可以使用 transceive()
方法发送命令。但是transceive()
方法有一个byte[]
参数,一个字节是8位。我想发送 0b1000000
(短帧)到我的 M1 卡。如何发送到M1卡?
/**
* Send raw NfcA data to a tag and receive the response.
*
* <p>This is equivalent to connecting to this tag via {@link NfcA}
* and calling {@link NfcA#transceive}. Note that all MIFARE Classic
* tags are based on {@link NfcA} technology.
*
* <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
* that can be sent with {@link #transceive}.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see NfcA#transceive
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
我的代码是:
/**
* Write a block of 16 byte data to tag.
* @param sectorIndex The sector to where the data should be written
* @param blockIndex The block to where the data should be written
* @param data 16 byte of data.
* @param key The MIFARE Classic key for the given sector.
* @param useAsKeyB If true, key will be treated as key B
* for authentication.
* @return The return codes are:<br />
* <ul>
* <li>0 - Everything went fine.</li>
* <li>1 - Sector index is out of range.</li>
* <li>2 - Block index is out of range.</li>
* <li>3 - Data are not 16 bytes.</li>
* <li>4 - Authentication went wrong.</li>
* <li>-1 - Error while writing to tag.</li>
* </ul>
* @see #authenticate(int, byte[], boolean)
*/
public int writeBlock(int sectorIndex, int blockIndex, byte[] data,
byte[] key, boolean useAsKeyB) {
if (getSectorCount()-1 < sectorIndex) {
return 1;
}
if (mMFC.getBlockCountInSector(sectorIndex)-1 < blockIndex) {
return 2;
}
if (data.length != 16) {
return 3;
}
int block = mMFC.sectorToBlock(sectorIndex) + blockIndex;
// write chinese card
if (block == 0) {
// Write block.
try {
mMFC.transceive(new byte[]{(byte)0x50, (byte)0x00, (byte)0x57, (byte)0xCD});
mMFC.transceive(new byte[]{(byte)0x40}); // TODO: here need send 0b1000000(7 bit) , not 0b01000000(8 bit)
mMFC.transceive(new byte[]{(byte)0x43});
mMFC.writeBlock(block, data);
} catch (IOException e) {
Log.e(LOG_TAG, "Error while writing block to tag.", e);
return -1;
}
return 0;
}
if (!authenticate(sectorIndex, key, useAsKeyB)) {
return 4;
}
// Write block.
try {
mMFC.writeBlock(block, data);
} catch (IOException e) {
Log.e(LOG_TAG, "Error while writing block to tag.", e);
return -1;
}
return 0;
}
您尝试做的事情在 Android 上根本不可能。 Android NFC API 不提供任何直接发送短帧(ISO/IEC 14443-3 Type A 中定义的 7 位帧)的方法。
事实上,NfcA
的 transceive()
方法不仅发送作为其参数传递的字节数组。相反,它还会导致 CRC 校验和自动附加到帧中。因此,您只能使用 transceive()
方法交换正常帧(如 ISO/IEC 14443-3 A 类中所定义)。
由于您使用的是 MIFARE Classic(或者更确切地说是一些 UID 可更改的克隆),您将在 Android 支持 MIFARE Classic 的设备(即具有 NXP 制造的 NFC 芯片组的设备)上遇到更多限制:如果检测到标签为 MIFARE Classic,NFC 控制器将切换到一种特殊模式,在该模式下,它会解释 MIFARE Classic 命令的高级版本,并自动将它们转换为低级(并可能加密)版本。这是必要的,因为 MIFARE Classic 不完全遵循 ISO/IEC 14443-3 Type A 的成帧规则。不幸的是,这通常也会阻止您将 any 原始帧直接发送到这些没有标签。
我在 Android 上使用 NFC 时遇到问题。我想向 M1 卡发送一些数据。我可以使用 transceive()
方法发送命令。但是transceive()
方法有一个byte[]
参数,一个字节是8位。我想发送 0b1000000
(短帧)到我的 M1 卡。如何发送到M1卡?
/**
* Send raw NfcA data to a tag and receive the response.
*
* <p>This is equivalent to connecting to this tag via {@link NfcA}
* and calling {@link NfcA#transceive}. Note that all MIFARE Classic
* tags are based on {@link NfcA} technology.
*
* <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
* that can be sent with {@link #transceive}.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see NfcA#transceive
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
我的代码是:
/**
* Write a block of 16 byte data to tag.
* @param sectorIndex The sector to where the data should be written
* @param blockIndex The block to where the data should be written
* @param data 16 byte of data.
* @param key The MIFARE Classic key for the given sector.
* @param useAsKeyB If true, key will be treated as key B
* for authentication.
* @return The return codes are:<br />
* <ul>
* <li>0 - Everything went fine.</li>
* <li>1 - Sector index is out of range.</li>
* <li>2 - Block index is out of range.</li>
* <li>3 - Data are not 16 bytes.</li>
* <li>4 - Authentication went wrong.</li>
* <li>-1 - Error while writing to tag.</li>
* </ul>
* @see #authenticate(int, byte[], boolean)
*/
public int writeBlock(int sectorIndex, int blockIndex, byte[] data,
byte[] key, boolean useAsKeyB) {
if (getSectorCount()-1 < sectorIndex) {
return 1;
}
if (mMFC.getBlockCountInSector(sectorIndex)-1 < blockIndex) {
return 2;
}
if (data.length != 16) {
return 3;
}
int block = mMFC.sectorToBlock(sectorIndex) + blockIndex;
// write chinese card
if (block == 0) {
// Write block.
try {
mMFC.transceive(new byte[]{(byte)0x50, (byte)0x00, (byte)0x57, (byte)0xCD});
mMFC.transceive(new byte[]{(byte)0x40}); // TODO: here need send 0b1000000(7 bit) , not 0b01000000(8 bit)
mMFC.transceive(new byte[]{(byte)0x43});
mMFC.writeBlock(block, data);
} catch (IOException e) {
Log.e(LOG_TAG, "Error while writing block to tag.", e);
return -1;
}
return 0;
}
if (!authenticate(sectorIndex, key, useAsKeyB)) {
return 4;
}
// Write block.
try {
mMFC.writeBlock(block, data);
} catch (IOException e) {
Log.e(LOG_TAG, "Error while writing block to tag.", e);
return -1;
}
return 0;
}
您尝试做的事情在 Android 上根本不可能。 Android NFC API 不提供任何直接发送短帧(ISO/IEC 14443-3 Type A 中定义的 7 位帧)的方法。
事实上,NfcA
的 transceive()
方法不仅发送作为其参数传递的字节数组。相反,它还会导致 CRC 校验和自动附加到帧中。因此,您只能使用 transceive()
方法交换正常帧(如 ISO/IEC 14443-3 A 类中所定义)。
由于您使用的是 MIFARE Classic(或者更确切地说是一些 UID 可更改的克隆),您将在 Android 支持 MIFARE Classic 的设备(即具有 NXP 制造的 NFC 芯片组的设备)上遇到更多限制:如果检测到标签为 MIFARE Classic,NFC 控制器将切换到一种特殊模式,在该模式下,它会解释 MIFARE Classic 命令的高级版本,并自动将它们转换为低级(并可能加密)版本。这是必要的,因为 MIFARE Classic 不完全遵循 ISO/IEC 14443-3 Type A 的成帧规则。不幸的是,这通常也会阻止您将 any 原始帧直接发送到这些没有标签。