已完成认证却无法向带密码保护的NTAG215写入URL的问题求助
问题:NTAG215认证成功后写入NDEF消息失败,抛出IOException(消息为null)
我尝试给带自定义密码保护的NTAG215写入URL,已正确设置PWD、PACK、AUTH0、AUTH_LIM和PROT参数,认证流程正常(返回的PACK与预设一致),但执行ndefTag.writeNdefMessage(message)时总是抛出消息为null的IOException。
认证代码片段
URLActivateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (myTag == null) { Toast.makeText(context, "my tag not detected", Toast.LENGTH_SHORT).show(); Toast.makeText(context, Error_detected, Toast.LENGTH_LONG).show(); } else { Ndef ndef_writable = Ndef.get(myTag); NfcA nfcA = NfcA.get(myTag); try { nfcA.connect(); // Intenta conectar con la tag NFC if (ndef_writable.isWritable()) { // Obtener la contraseña en formato de bytes byte[] passwordBytes = getPasswordBytes(); try { // Enviar el comando PWD_AUTH al tag NFC byte[] response = nfcA.transceive(new byte[] { (byte) 0x1B, // PWD_AUTH passwordBytes[0], passwordBytes[1], passwordBytes[2], passwordBytes[3] }); if ((response != null) && (response.length >= 2)) { // Obtener PACK para verificar la autenticidad del tag byte[] pack = Arrays.copyOf(response, 2); // Verificar PACK para confirmar que el tag es auténtico if (verifyPack(pack)) { nfcA.close(); // Autenticación exitosa, ahora puedes realizar la escritura en la tag writeURLtoTag(myTag, createUriMessage(edit_url.getText().toString())); Toast.makeText(context, Write_Succes, Toast.LENGTH_LONG).show(); //... rest of the code
写入函数代码片段
public void writeURLtoTag(Tag tag, NdefMessage message) { if (tag != null) { try { Ndef ndefTag = Ndef.get(tag); if (ndefTag == null) { // Let's try to format the Tag in NDEF NdefFormatable nForm = NdefFormatable.get(tag); if (nForm != null) { // Formatear la etiqueta si es necesario nForm.connect(); nForm.format(message); nForm.close(); } else { // Manejar el caso en que la etiqueta no sea compatible con NDEF ni NdefFormatable Log.e("TagAuth", "Tag not compatible with NDEF"); Toast.makeText(context, "Tag not compatible with NDEF", Toast.LENGTH_SHORT).show(); } } else { // Verificar el contenido actual de la etiqueta antes de escribir NdefMessage currentMessage = ndefTag.getCachedNdefMessage(); if (currentMessage != null) { // Puedes imprimir o manejar el contenido actual de la etiqueta si es necesario Log.d("TagAuth", "Current NDEF Message: " + currentMessage.toString()); } // Continuar con la conexión y escritura en la etiqueta ndefTag.connect(); try { checkTagStatus(tag); ndefTag.writeNdefMessage(message); Toast.makeText(context, "Write Successful", Toast.LENGTH_SHORT).show(); } catch (IOException e) { Log.e("TagAuth", "IOException during writeNdefMessage: " + e.getMessage()); Toast.makeText(context, "IOException during writeNdefMessage", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } ndefTag.close(); } } catch(Exception e) { Log.e("TagAuth", "Error during write Ndef: " + e.toString()); Toast.makeText(context, "Writing Error", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } }
解决方案
1. 修复认证会话丢失问题
NTAG215的认证状态是会话绑定的:你在nfcA.connect()会话中完成认证后,直接关闭了nfcA连接,后续调用writeURLtoTag时,ndefTag.connect()会建立全新的NFC会话,之前的认证状态不会保留,导致写入时无权限,触发IOException。
解决方法:复用同一个NFC连接会话完成认证和写入,不要在认证后关闭nfcA。示例修改:
if (verifyPack(pack)) { // 注释掉nfcA.close(),复用当前会话 // nfcA.close(); Ndef ndefTag = Ndef.get(myTag); if (ndefTag != null) { try { ndefTag.connect(); ndefTag.writeNdefMessage(createUriMessage(edit_url.getText().toString())); Toast.makeText(context, Write_Succes, Toast.LENGTH_LONG).show(); } catch (Exception e) { Log.e("TagAuth", "Write failed: " + e.getMessage()); Toast.makeText(context, "Write failed", Toast.LENGTH_SHORT).show(); } finally { ndefTag.close(); nfcA.close(); // 最后统一关闭连接 } } }
2. 检查AUTH0和PROT参数配置
- 确认AUTH0设置的起始块地址正确:NTAG215的NDEF数据区默认从块4开始,若AUTH0设为4,则块4及之后的操作都需要认证。
- 确保PROT参数为0:如果PROT设为1,认证后标签会变为只读状态,无法写入。
可通过读取配置块(块3)验证参数:
// 在nfcA连接状态下读取块3 byte[] block3 = nfcA.transceive(new byte[]{(byte)0x30, 0x03}); // READ_BLOCK命令 int auth0 = block3[2] & 0xFF; int prot = (block3[3] >> 6) & 0x01; Log.d("TagConfig", "AUTH0: " + auth0 + ", PROT: " + prot);
3. 验证NdefMessage有效性
检查createUriMessage生成的消息是否格式正确、容量不超过标签限制(NTAG215的NDEF可用容量约137字节):
NdefMessage message = createUriMessage(edit_url.getText().toString()); Log.d("NDEFCheck", "Message byte length: " + message.toByteArray().length);
内容的提问来源于stack exchange,提问作者Iker Busteros
相关产品推荐
相关产品推荐

