2017-08-04 164 views
1

它全部開始here。那邊的問題解決了,現在我面臨使用收發方法的問題。NfcA.transceive(byte [] data)throws TagLostException

我的代碼如下所示:

private void writeAndProtectTag(final Intent intent, final String message) { 
    // Run the entire process in its own thread as NfcA.transceive(byte[] data); 
    // Should not be run in main thread according to <https://developer.android.com/reference/android/nfc/tech/NfcA.html#transceive(byte[])> 
    (new Thread(new Runnable() { 
     // Password has to be 4 characters 
     // Password Acknowledge has to be 2 characters 
     byte[] pwd  = "-_bA".getBytes(); 
     byte[] pack  = "cC".getBytes(); 

     @Override 
     public void run() { 
      // Store tag object for use in NfcA and Ndef 
      Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 
      // Using NfcA instead of MifareUltralight should make no difference in this method 
      NfcA nfca = null; 

      // Whole process is put into a big try-catch trying to catch the transceive's IOException 
      try { 
       nfca = NfcA.get(tag); 

       nfca.connect(); 

       byte[] response; 

       // Authenticate with the tag first 
       // In case it's already been locked 
       try { 
        response = nfca.transceive(new byte[]{ 
          (byte) 0x1B, // PWD_AUTH 
          pwd[0], pwd[1], pwd[2], pwd[3] 
        }); 

        // Check if PACK is matching expected PACK 
        // This is a (not that) secure method to check if tag is genuine 
        if ((response != null) && (response.length >= 2)) { 
         byte[] packResponse = Arrays.copyOf(response, 2); 
         if (!(pack[0] == packResponse[0] && pack[1] == packResponse[1])) { 
          Toast.makeText(ctx, "Tag could not be authenticated:\n" + packResponse.toString() + "≠" + pack.toString(), Toast.LENGTH_LONG).show(); 
         } 
        } 
       }catch(TagLostException e){ 
        e.printStackTrace(); 
       } 

       // Get Page 2Ah 
       response = nfca.transceive(new byte[] { 
         (byte) 0x30, // READ 
         (byte) 0x2A // page address 
       }); 
       // configure tag as write-protected with unlimited authentication tries 
       if ((response != null) && (response.length >= 16)) { // read always returns 4 pages 
        boolean prot = false;        // false = PWD_AUTH for write only, true = PWD_AUTH for read and write 
        int authlim = 0;         // 0 = unlimited tries 
        nfca.transceive(new byte[] { 
          (byte) 0xA2, // WRITE 
          (byte) 0x2A, // page address 
          (byte) ((response[0] & 0x078) | (prot ? 0x080 : 0x000) | (authlim & 0x007)), // set ACCESS byte according to our settings 
          0, 0, 0                   // fill rest as zeros as stated in datasheet (RFUI must be set as 0b) 
        }); 
       } 
       // Get page 29h 
       response = nfca.transceive(new byte[] { 
         (byte) 0x30, // READ 
         (byte) 0x29 // page address 
       }); 
       // Configure tag to protect entire storage (page 0 and above) 
       if ((response != null) && (response.length >= 16)) { // read always returns 4 pages 
        int auth0 = 0;         // first page to be protected 
        nfca.transceive(new byte[] { 
          (byte) 0xA2, // WRITE 
          (byte) 0x29, // page address 
          response[0], 0, response[2],    // Keep old mirror values and write 0 in RFUI byte as stated in datasheet 
          (byte) (auth0 & 0x0ff) 
        }); 
       } 

       // Send PACK and PWD 
       // set PACK: 
       nfca.transceive(new byte[] { 
         (byte)0xA2, 
         (byte)0x2C, 
         pack[0], pack[1], 0, 0 // Write PACK into first 2 Bytes and 0 in RFUI bytes 
       }); 
       // set PWD: 
       nfca.transceive(new byte[] { 
         (byte)0xA2, 
         (byte)0x2B, 
         pwd[0], pwd[1], pwd[2], pwd[3] // Write all 4 PWD bytes into Page 43 
       }); 

       // Generate NdefMessage to be written onto the tag 
       NdefMessage msg = null; 
       try { 
        NdefRecord r1 = NdefRecord.createMime("text/plain", message.getBytes("UTF-8")); 
        NdefRecord r2 = NdefRecord.createApplicationRecord("com.example.alex.nfcapppcekunde"); 
        msg = new NdefMessage(r1, r2); 
       } catch (UnsupportedEncodingException e) { 
        e.printStackTrace(); 
       } 

       byte[] ndefMessage = msg.toByteArray(); 

       nfca.transceive(new byte[] { 
         (byte)0xA2, // WRITE 
         (byte)3, // block address 
         (byte)0xE1, (byte)0x10, (byte)0x12, (byte)0x00 
       }); 

       // wrap into TLV structure 
       byte[] tlvEncodedData = null; 

       tlvEncodedData = new byte[ndefMessage.length + 3]; 
       tlvEncodedData[0] = (byte)0x03; // NDEF TLV tag 
       tlvEncodedData[1] = (byte)(ndefMessage.length & 0x0FF); // NDEF TLV length (1 byte) 
       System.arraycopy(ndefMessage, 0, tlvEncodedData, 2, ndefMessage.length); 
       tlvEncodedData[2 + ndefMessage.length] = (byte)0xFE; // Terminator TLV tag 

       // fill up with zeros to block boundary: 
       tlvEncodedData = Arrays.copyOf(tlvEncodedData, (tlvEncodedData.length/4 + 1) * 4); 
       for (int i = 0; i < tlvEncodedData.length; i += 4) { 
        byte[] command = new byte[] { 
          (byte)0xA2, // WRITE 
          (byte)((4 + i/4) & 0x0FF), // block address 
          0, 0, 0, 0 
        }; 
        System.arraycopy(tlvEncodedData, i, command, 2, 4); 
        try { 
         response = nfca.transceive(command); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         //UI related things, not important for NFC 
         btn.setImageResource(R.drawable.arrow_red); 
         tv.setText(""); 
        } 
       }); 
       curAction = "handle"; 

       try { 
        nfca.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

      } catch (IOException e) { 
       //Trying to catch any ioexception that may be thrown 
       e.printStackTrace(); 
      } catch (Exception e) { 
       //Trying to catch any exception that may be thrown 
       e.printStackTrace(); 
      } 

     } 
    })).start(); 
} 

,所用Ndef類寫上,我沒有這個問題的標籤我的舊代碼版本。現在,我改變了一些東西,我獲得兩個TagLostException S:

  • 一個從線PWD_AUTH命令失敗,但它的異常被捕獲,這實際上是打算作爲標籤我掃描沒有密碼尚未設置。
  • 另一個來自讀取配置的收發器。

在第二個TagLostException之後,該方法當然結束。閱讀配置時,我不應該得到TagLostException。有人知道那裏發生了什麼嗎?

這裏的例外:

android.nfc.TagLostException: Tag was lost. 
          at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:48) 
          at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151) 
          at android.nfc.tech.NfcA.transceive(NfcA.java:129) 
          at com.example.alex.nfcapppce.MainActivity$2.run(MainActivity.java:134) 
          at java.lang.Thread.run(Thread.java:761) 
    android.nfc.TagLostException: Tag was lost. 
          at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:48) 
          at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151) 
          at android.nfc.tech.NfcA.transceive(NfcA.java:129) 
          at com.example.alex.nfcapppce.MainActivity$2.run(MainActivity.java:155) 
          at java.lang.Thread.run(Thread.java:761) 

回答

0

解決:

當試圖與不具有保護尚未通信剛剛崩潰拋出一個適當的異常趕上,而不是一個標籤進行身份驗證,因爲我我沒有注意到應用程序繼續嘗試收發數據的異常,但標籤「丟失了」,因爲現在稱爲Exception是告訴我的。

要知道,如果標籤已受到保護,檢查Auth0爲集保護:

byte[] response; 

//Read page 41 on NTAG213, will be different for other tags 
response = mifare.transceive(new byte[] { 
     (byte) 0x30, // READ 
     41   // page address 
}); 
// Authenticate with the tag first 
// only if the Auth0 byte is not 0xFF, 
// which is the default value meaning unprotected 
if(response[3] != (byte)0xFF) { 
    try { 
     response = mifare.transceive(new byte[]{ 
       (byte) 0x1B, // PWD_AUTH 
       pwd[0], pwd[1], pwd[2], pwd[3] 
     }); 
     // Check if PACK is matching expected PACK 
     // This is a (not that) secure method to check if tag is genuine 
     if ((response != null) && (response.length >= 2)) { 
      final byte[] packResponse = Arrays.copyOf(response, 2); 
      if (!(pack[0] == packResponse[0] && pack[1] == packResponse[1])) {runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(ctx, "Tag could not be authenticated:\n" + packResponse.toString() + "≠" + pack.toString(), Toast.LENGTH_LONG).show(); 
       } 
      }); 
      }else{ 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Toast.makeText(ctx, "Tag successfully authenticated!", Toast.LENGTH_SHORT).show(); 
        } 
       }); 
      } 
     } 
    } catch (TagLostException e) { 
     e.printStackTrace(); 
    } 
}else{ 
    // Protect tag with your password in case 
    // it's not protected yet 

    // Get Page 2Ah 
    response = mifare.transceive(new byte[] { 
      (byte) 0x30, // READ 
      (byte) 0x2A // page address 
    }); 
    // configure tag as write-protected with unlimited authentication tries 
    if ((response != null) && (response.length >= 16)) { // read always returns 4 pages 
     boolean prot = false;        // false = PWD_AUTH for write only, true = PWD_AUTH for read and write 
     int authlim = 0;         // 0 = unlimited tries 
     mifare.transceive(new byte[] { 
       (byte) 0xA2, // WRITE 
       (byte) 0x2A, // page address 
       (byte) ((response[0] & 0x078) | (prot ? 0x080 : 0x000) | (authlim & 0x007)), // set ACCESS byte according to our settings 
       0, 0, 0                   // fill rest as zeros as stated in datasheet (RFUI must be set as 0b) 
     }); 
    } 
    // Get page 29h 
    response = mifare.transceive(new byte[] { 
      (byte) 0x30, // READ 
      (byte) 0x29 // page address 
    }); 
    // Configure tag to protect entire storage (page 0 and above) 
    if ((response != null) && (response.length >= 16)) { // read always returns 4 pages 
     int auth0 = 0;         // first page to be protected 
     mifare.transceive(new byte[] { 
       (byte) 0xA2, // WRITE 
       (byte) 0x29, // page address 
       response[0], 0, response[2],    // Keep old mirror values and write 0 in RFUI byte as stated in datasheet 
       (byte) (auth0 & 0x0ff) 
     }); 
    } 

    // Send PACK and PWD 
    // set PACK: 
    mifare.transceive(new byte[] { 
      (byte)0xA2, 
      (byte)0x2C, 
      pack[0], pack[1], 0, 0 // Write PACK into first 2 Bytes and 0 in RFUI bytes 
    }); 
    // set PWD: 
    mifare.transceive(new byte[] { 
      (byte)0xA2, 
      (byte)0x2B, 
      pwd[0], pwd[1], pwd[2], pwd[3] // Write all 4 PWD bytes into Page 43 
    }); 
} 
0

您嘗試讀取任何數據之前進行身份驗證的標籤。根據您使用的特定Android設備,如果身份驗證失敗,您將收到NACK響應或IOException(通常但不總是(?),TagLostException)。在你目前忽略此錯誤兩種情況下(你放下例外,你只處理成功的結果((response != null) && (response.length >= 2)),因此,您的代碼(並保持)處於錯誤狀態時,認證失敗。

因此,您需要妥善處理。這些錯誤條件通常情況下,你將要關閉並重新打開後,每一個錯誤的連接(NACK響應,響應nullIOException),你可以很容易地實現這在您的代碼:

nfca.connect(); 

byte[] response; 
boolean authError = true; 

// Authenticate with the tag first 
try { 
    response = nfca.transceive(new byte[]{ 
      (byte) 0x1B, // PWD_AUTH 
      pwd[0], pwd[1], pwd[2], pwd[3] 
    }); 

    // Check if PACK is matching expected PACK 
    if ((response != null) && (response.length >= 2)) { 
     authError = false; 

     [...] 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

if (authError) { 
    try { 
     nfca.close(); 
    } catch (Exception ignored) {} 
    nfca.connect(); 
} 

// Get Page 2Ah 
response = nfca.transceive(new byte[] { 
     (byte) 0x30, // READ 
     (byte) 0x2A // page address 
}); 

[...] 
相關問題