You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android NFC写入WiFi配置标签后扫描无响应问题求助

问题分析与解决方案

核心问题

你当前的代码错误理解了WSC(WiFi Simple Configuration)的NFC标签格式规范:

  • application/vnd.wfa.wsc类型的NDEF记录要求携带完整的WSC二进制TLV数据包,而非仅传入SSID字节再附加文本记录。
  • 系统NFC服务只会识别符合WSC标准的完整数据包,当前构造的NdefMessage不符合规范,因此扫描标签后无任何响应。

正确实现方案

需要按照WSC规范构造包含SSID、密码、认证类型等核心信息的TLV(Type-Length-Value)结构,再封装成NDEF记录写入标签。以下是修正后的NFCUtils代码:

import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import java.nio.charset.StandardCharsets;

public class NFCUtils {

    // WSC规范常量定义
    private static final byte WSC_VERSION = (byte) 0x10;
    private static final byte WSC_TYPE_SSID = 0x10;
    private static final byte WSC_TYPE_NETWORK_KEY = 0x12;
    private static final byte WSC_TYPE_AUTH_TYPE = 0x03;
    private static final byte WSC_TYPE_ENCRYPT_TYPE = 0x04;
    private static final byte AUTH_WPA2_PSK = (byte) 0x0008;
    private static final byte ENCRYPT_AES = (byte) 0x0008;

    public static void writeWifiConfigToTag(Tag tag, String ssid, String password) {
        // 构造符合WSC规范的TLV数据包
        byte[] wscTlvData = buildWscTlvPacket(ssid, password);
        // 创建标准WSC NDEF记录
        NdefRecord wscRecord = NdefRecord.createMime("application/vnd.wfa.wsc", wscTlvData);
        NdefMessage wifiMessage = new NdefMessage(new NdefRecord[]{wscRecord});

        // 写入标签逻辑
        Ndef ndef = Ndef.get(tag);
        if (ndef == null) return;

        try {
            ndef.connect();
            if (!ndef.isWritable()) throw new IllegalStateException("标签不可写入");
            if (ndef.getMaxSize() < wifiMessage.toByteArray().length) throw new IllegalStateException("标签容量不足");
            
            ndef.writeNdefMessage(wifiMessage);
            ndef.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static byte[] buildWscTlvPacket(String ssid, String password) {
        // 构造单个TLV字段
        byte[] versionTlv = buildTlv((byte) 0x00, new byte[]{WSC_VERSION});
        byte[] authTlv = buildTlv(WSC_TYPE_AUTH_TYPE, new byte[]{AUTH_WPA2_PSK});
        byte[] encryptTlv = buildTlv(WSC_TYPE_ENCRYPT_TYPE, new byte[]{ENCRYPT_AES});
        byte[] ssidTlv = buildTlv(WSC_TYPE_SSID, ssid.getBytes(StandardCharsets.UTF_8));
        byte[] passwordTlv = buildTlv(WSC_TYPE_NETWORK_KEY, password.getBytes(StandardCharsets.UTF_8));

        // 合并所有TLV字段
        byte[] fullPacket = new byte[versionTlv.length + authTlv.length + encryptTlv.length + ssidTlv.length + passwordTlv.length];
        int offset = 0;
        
        System.arraycopy(versionTlv, 0, fullPacket, offset, versionTlv.length);
        offset += versionTlv.length;
        System.arraycopy(authTlv, 0, fullPacket, offset, authTlv.length);
        offset += authTlv.length;
        System.arraycopy(encryptTlv, 0, fullPacket, offset, encryptTlv.length);
        offset += encryptTlv.length;
        System.arraycopy(ssidTlv, 0, fullPacket, offset, ssidTlv.length);
        offset += ssidTlv.length;
        System.arraycopy(passwordTlv, 0, fullPacket, offset, passwordTlv.length);

        return fullPacket;
    }

    private static byte[] buildTlv(byte type, byte[] value) {
        // TLV格式:Type(1字节) + Length(2字节大端) + Value(n字节)
        byte[] tlv = new byte[1 + 2 + value.length];
        tlv[0] = type;
        tlv[1] = (byte) ((value.length >> 8) & 0xFF);
        tlv[2] = (byte) (value.length & 0xFF);
        System.arraycopy(value, 0, tlv, 3, value.length);
        return tlv;
    }
}

补充说明

  • WSC规范强制要求包含版本、认证类型、加密类型、SSID、密码这些核心TLV字段,缺失任何一个都会导致系统无法识别。
  • 代码默认使用当前主流的WPA2-PSK认证+AES加密组合,若你的WiFi使用WPA3等其他标准,需修改对应的认证/加密常量值。
  • 写入前增加了标签可写性、容量检查,避免无意义的写入失败。

内容的提问来源于stack exchange,提问作者Iker Busteros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:01:47