【问题标题】:Cannot format NdefFormatable NFC tag无法格式化 NdefFormatable NFC 标签
【发布时间】:2018-08-10 03:21:38
【问题描述】:

我正在开发一个使用 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$000(MainActivity.java:27)
                  at com.example.peng.nfcreadwrite.MainActivity$1.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 “未找到密钥(或死扇区)”:

【问题讨论】:

  • 该标签以前是否用于其他用途?会不会是 MIFARE Classic 卡的某些扇区被除了传输密钥之外的其他密钥锁定了?您可能想尝试使用一些通用标签阅读器应用程序(例如我的 NFC TagInfo 或 NXP TagInfo)来读取标签,以验证所有扇区都可以使用传输密钥写入。
  • 很抱歉回复晚了,这些卡是我工作场所使用的某个第三方供应商提供的,他们说这是一张空白卡。我使用 Mifare Classic Tool 进行了检查,发现所有卡的扇区 4 到 8 都显示消息未找到密钥(或死扇区)。 (请参阅我更新的问题以获取我检查的卡的屏幕截图)
  • 您好,我也遇到了同样的问题,并在这里发了一个问题stackoverflow.com/questions/61784673/…你能分享一个完整的解决方案吗?

标签: android format nfc mifare ndef


【解决方案1】:

Android 上 MIFARE Classic 标记的 NDEF 格式化过程要求标记为空且可使用默认传输密钥 (FFFFFFFFFFFF) 或某些标准密钥(扇区 0 的 MAD 密钥、扇区 0 的 NDEF 密钥)访问(读取和写入)其他部门)。如果标签的某些扇区不可访问,Android 将无法格式化标签以用于 NDEF。

因此,您的标签无法用于您的目的。尽管您可以手动格式化标签以跳过那些锁定的扇区。我不太确定Android是否能够使用这些标签。

【讨论】:

  • 您的回答使我相信我自己的建议。标签具有访问这些扇区的一些密钥。我没有钥匙,所以我无法读取/重写它们。在我买了一些空白标签后,我可以使用我的代码顺利写入它们,感谢@MichaelRoland给我一些启示。
【解决方案2】:

您可以使用以下代码读写 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;
 }

【讨论】:

    猜你喜欢
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多