无法格式化 NdefFormatable NFC 标签
Cannot format NdefFormatable NFC tag
我正在开发一个使用 NFC 的 Android 应用程序。我有一些具有以下技术列表的 NFC 卡:
- android.nfc.tech.NfcA
- android.nfc.tech.MifareClassic
- android.nfc.tech.NdefFormatable
但我无法使用 NdefFormatable.format(message)
格式化这些标签。相反,我得到一个 IOException。
代码:
try {
NdefRecord[] records1 = { createRecord("000000") };
NdefMessage message1 = new NdefMessage(records1);
formatable.format(message1);
res = 1;
}
堆栈跟踪给出了这些日志:
W/System.err: java.io.IOException
W/System.err: at android.nfc.tech.NdefFormatable.format(NdefFormatable.java:131)
W/System.err: at android.nfc.tech.NdefFormatable.format(NdefFormatable.java:94)
at com.example.peng.nfcreadwrite.MainActivity.write(MainActivity.java:170)
W/System.err: at com.example.peng.nfcreadwrite.MainActivity.access[=11=]0(MainActivity.java:27)
at com.example.peng.nfcreadwrite.MainActivity.onClick(MainActivity.java:60)
at android.view.View.performClick(View.java:6877)
W/System.err: at android.widget.TextView.performClick(TextView.java:12651)
at android.view.View$PerformClick.run(View.java:26069)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
W/System.err: at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
也许有人可以给我一些东西来研究,因为我对 Android 上的 NFC 还很陌生。
编辑
这是我使用 Mifare Classic Tool 截取的屏幕截图。它显示扇区 4 到 8 "no keys found(or dead sector)":
Android 上 MIFARE Classic 标签的 NDEF 格式化程序要求标签为空且可使用默认传输密钥 (FFFFFFFFFFFF
) 或某些标准密钥 (MAD) 访问(读取和写入)扇区 0 的密钥,其他扇区的 NDEF 密钥)。如果标签的某些扇区不可访问,Android 将无法格式化标签以用于 NDEF。
因此,您的标签无法用于您的目的。尽管您可以手动格式化标签以跳过那些锁定的扇区。我不太确定 Android 是否能够使用这些标签。
您可以使用以下代码读写Mifare Classic
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
// Toast.makeText(this, "MyTag :"+myTag, Toast.LENGTH_SHORT).show();
byte[] tagId = getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID);
Toast.makeText(this, "this is Tagid:" + tagId, Toast.LENGTH_SHORT).show();
NfcSn = Hex.bytesToStringLowercase( tagId );
System.out.println( "Tag Id"+NfcSn);
MifareClassic mif = MifareClassic.get(myTag);
//here is how to authenticate
try {
mif.connect();
if (mif.isConnected()) {
boolean isAuthenticated = false;
if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY)) {
isAuthenticated = true;
} else if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_DEFAULT)) {
isAuthenticated = true;
} else if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_NFC_FORUM)) {
isAuthenticated = true;
} else {
int block_index = mif.sectorToBlock(1);
byte[] block = mif.readBlock(block_index);
String s_block = Hex.bytesToStringLowercase( block );
System.out.println(s_block);
}
int block_index = mif.sectorToBlock(1);
//here is how to read
byte[] block = mif.readBlock(block_index);
String s_block = Hex.bytesToStringLowercase( block );
byte[] stringByte = hexStringToByteArray(s_block);
String data = new String(stringByte,"UTF-8");
System.out.println(data);
System.out.println(s_block);
System.out.println("is auth :"+isAuthenticated);
//here is how to write
mif.writeBlock(mif.sectorToBlock(1), new byte[]{'H', 'a', 'f', 'i', 'z', ' ', 'D', 'a', 'n', 'm', 'a', 'n', 'u', ' ', ' ', ' '});
mif.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
setIntent(intent);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
我正在开发一个使用 NFC 的 Android 应用程序。我有一些具有以下技术列表的 NFC 卡:
- android.nfc.tech.NfcA
- android.nfc.tech.MifareClassic
- android.nfc.tech.NdefFormatable
但我无法使用 NdefFormatable.format(message)
格式化这些标签。相反,我得到一个 IOException。
代码:
try {
NdefRecord[] records1 = { createRecord("000000") };
NdefMessage message1 = new NdefMessage(records1);
formatable.format(message1);
res = 1;
}
堆栈跟踪给出了这些日志:
W/System.err: java.io.IOException
W/System.err: at android.nfc.tech.NdefFormatable.format(NdefFormatable.java:131)
W/System.err: at android.nfc.tech.NdefFormatable.format(NdefFormatable.java:94)
at com.example.peng.nfcreadwrite.MainActivity.write(MainActivity.java:170)
W/System.err: at com.example.peng.nfcreadwrite.MainActivity.access[=11=]0(MainActivity.java:27)
at com.example.peng.nfcreadwrite.MainActivity.onClick(MainActivity.java:60)
at android.view.View.performClick(View.java:6877)
W/System.err: at android.widget.TextView.performClick(TextView.java:12651)
at android.view.View$PerformClick.run(View.java:26069)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
W/System.err: at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
也许有人可以给我一些东西来研究,因为我对 Android 上的 NFC 还很陌生。
编辑
这是我使用 Mifare Classic Tool 截取的屏幕截图。它显示扇区 4 到 8 "no keys found(or dead sector)":
Android 上 MIFARE Classic 标签的 NDEF 格式化程序要求标签为空且可使用默认传输密钥 (FFFFFFFFFFFF
) 或某些标准密钥 (MAD) 访问(读取和写入)扇区 0 的密钥,其他扇区的 NDEF 密钥)。如果标签的某些扇区不可访问,Android 将无法格式化标签以用于 NDEF。
因此,您的标签无法用于您的目的。尽管您可以手动格式化标签以跳过那些锁定的扇区。我不太确定 Android 是否能够使用这些标签。
您可以使用以下代码读写Mifare Classic
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
// Toast.makeText(this, "MyTag :"+myTag, Toast.LENGTH_SHORT).show();
byte[] tagId = getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID);
Toast.makeText(this, "this is Tagid:" + tagId, Toast.LENGTH_SHORT).show();
NfcSn = Hex.bytesToStringLowercase( tagId );
System.out.println( "Tag Id"+NfcSn);
MifareClassic mif = MifareClassic.get(myTag);
//here is how to authenticate
try {
mif.connect();
if (mif.isConnected()) {
boolean isAuthenticated = false;
if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY)) {
isAuthenticated = true;
} else if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_DEFAULT)) {
isAuthenticated = true;
} else if (mif.authenticateSectorWithKeyA(1, MifareClassic.KEY_NFC_FORUM)) {
isAuthenticated = true;
} else {
int block_index = mif.sectorToBlock(1);
byte[] block = mif.readBlock(block_index);
String s_block = Hex.bytesToStringLowercase( block );
System.out.println(s_block);
}
int block_index = mif.sectorToBlock(1);
//here is how to read
byte[] block = mif.readBlock(block_index);
String s_block = Hex.bytesToStringLowercase( block );
byte[] stringByte = hexStringToByteArray(s_block);
String data = new String(stringByte,"UTF-8");
System.out.println(data);
System.out.println(s_block);
System.out.println("is auth :"+isAuthenticated);
//here is how to write
mif.writeBlock(mif.sectorToBlock(1), new byte[]{'H', 'a', 'f', 'i', 'z', ' ', 'D', 'a', 'n', 'm', 'a', 'n', 'u', ' ', ' ', ' '});
mif.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
setIntent(intent);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}