2012-10-26 103 views
3

有谁知道我可以通过Android NFC API找出哪个NFC芯片用于我正在阅读的标签中?理想情况下,我喜欢获得芯片型号和制造商。如何检测NFC芯片的类型

是否可以在Tag对象的某个地方使用?

为了澄清,我并不是指手机中的读卡器芯片,而是NFC标签中的芯片。

回答

11

我正在开发一款Android应用程序,用于NFC读/写/验证操作。以下是您需要的一些代码部分。

Android有三种主要卡类型,分别是Mifare Classic,Mifare Ultralight和Isodep(这是Desfire和Desfire EV1的类型)。所以,我得到一个标签感动,我运行这个操作:

private String[] getTagInfo(Intent intent) { 
    Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 
    String prefix = "android.nfc.tech."; 
    String[] info = new String[2]; 

    // UID 
    byte[] uid = tag.getId(); 
    info[0] = "UID In Hex: " + Utils.convertByteArrayToHexString(uid) + "\n" + 
       "UID In Dec: " + Utils.convertByteArrayToDecimal(uid) + "\n\n"; 

    // Tech List 
    String[] techList = tag.getTechList(); 
    String techListConcat = "Technologies: "; 
    for(int i = 0; i < techList.length; i++) { 
     techListConcat += techList[i].substring(prefix.length()) + ","; 
    } 
    info[0] += techListConcat.substring(0, techListConcat.length() - 1) + "\n\n"; 

    // Mifare Classic/UltraLight Info 
    info[0] += "Card Type: "; 
    String type = "Unknown"; 
    for(int i = 0; i < techList.length; i++) { 
     if(techList[i].equals(MifareClassic.class.getName())) { 
      info[1] = "Mifare Classic"; 
      MifareClassic mifareClassicTag = MifareClassic.get(tag); 

      // Type Info 
      switch (mifareClassicTag.getType()) { 
      case MifareClassic.TYPE_CLASSIC: 
       type = "Classic"; 
       break; 
      case MifareClassic.TYPE_PLUS: 
       type = "Plus"; 
       break; 
      case MifareClassic.TYPE_PRO: 
       type = "Pro"; 
       break; 
      } 
      info[0] += "Mifare " + type + "\n"; 

      // Size Info 
      info[0] += "Size: " + mifareClassicTag.getSize() + " bytes \n" + 
        "Sector Count: " + mifareClassicTag.getSectorCount() + "\n" + 
        "Block Count: " + mifareClassicTag.getBlockCount() + "\n"; 
     } else if(techList[i].equals(MifareUltralight.class.getName())) { 
      info[1] = "Mifare UltraLight"; 
      MifareUltralight mifareUlTag = MifareUltralight.get(tag); 

      // Type Info 
      switch (mifareUlTag.getType()) { 
      case MifareUltralight.TYPE_ULTRALIGHT: 
       type = "Ultralight"; 
       break; 
      case MifareUltralight.TYPE_ULTRALIGHT_C: 
       type = "Ultralight C"; 
       break; 
      } 
      info[0] += "Mifare " + type + "\n"; 
     } else if(techList[i].equals(IsoDep.class.getName())) { 
      info[1] = "IsoDep"; 
      IsoDep isoDepTag = IsoDep.get(tag); 
      info[0] += "IsoDep \n"; 
     } else if(techList[i].equals(Ndef.class.getName())) { 
      Ndef ndefTag = Ndef.get(tag); 
      info[0] += "Is Writable: " + ndefTag.isWritable() + "\n" + 
        "Can Make ReadOnly: " + ndefTag.canMakeReadOnly() + "\n"; 
     } else if(techList[i].equals(NdefFormatable.class.getName())) { 
      NdefFormatable ndefFormatableTag = NdefFormatable.get(tag); 
     } 
    } 

    return info; 
} 

然而,这并不直接获得的DESFire和DESFire非EV1的类型。对于那些你需要一些字节,发送到卡:

static final byte GET_MANUFACTURING_DATA = (byte) 0x60; 

public DesfireManufacturingData getManufacturingData() throws Exception { 
    byte[] respBuffer = sendRequest(GET_MANUFACTURING_DATA); 
    if (respBuffer.length != 28) 
     throw new Exception("Invalid response"); 
    return new DesfireManufacturingData(respBuffer); 
} 

private byte[] sendRequest (byte command) throws Exception { 
    return sendRequest(command, null); 
} 

private byte[] sendRequest (byte command, byte[] parameters) throws Exception { 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    byte[] recvBuffer = mTagTech.transceive(Utils.wrapMessage(command, parameters)); 

    while (true) { 
     if (recvBuffer[recvBuffer.length - 2] != (byte) 0x91) 
      throw new Exception("Invalid response"); 

     output.write(recvBuffer, 0, recvBuffer.length - 2); 

     byte status = recvBuffer[recvBuffer.length - 1]; 
     if (status == OPERATION_OK) { 
      break; 
     } else if (status == ADDITIONAL_FRAME) { 
      recvBuffer = mTagTech.transceive(Utils.wrapMessage(GET_ADDITIONAL_FRAME, null)); 


     } else if (status == PERMISSION_DENIED) { 
      throw new Exception("Permission denied"); 
     }else if (status == LENGTH_ERROR) { 
      throw new Exception("Length Error"); 
     } 
     else if (status == AUTHENTICATION_ERROR) { 
      throw new Exception("Authentication error"); 
     }else if (status == PARAMETER_ERROR) { 
      throw new Exception("Parameter Error"); 
     }else if (status == DUPLICATE_ERROR) { 
      throw new Exception("Duplicate Error"); 
     }else if (status == NO_SUCH_KEY) { 
      throw new Exception("No such key"); 
     }else { 
      throw new Exception("Unknown status code: " + Integer.toHexString(status & 0xFF)); 
     } 
    } 

    return output.toByteArray(); 
} 

后您初始化制造业数据,你可以很容易地达到其部分。 DesfireManufacturingData类用于评估从标签到有意义的部分的响应,但我只给出它的链接:Desfire Manufacturing Data。另外,我必须说这是我在互联网上用开放源代码找到的最全面的项目,但它只有Desfire标记的读取操作,而不是写入和验证。希望这可以帮助!

+0

感谢分享。我会试一试 – corvairjo

+0

干得好相当有帮助。 –

1

如果您拥有带NFC的Android设备,则有多种应用可以完成此操作(以及更多),例如NXP TagInfoNFC TagInfo

对于配台式阅读器的PC,可能有RFIDIOt。对于其他平台,类似的应用程序可能存在(或可能被创建),但我不熟悉它们。

+0

我知道恩智浦的应用程序。不过,我想在我自己的应用程序中做到这一点。因此,我想知道我会在哪里获得这些信息,以便我可以通过SW获取信息。谢谢 – corvairjo