You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Processing Android连接扫描到的未知WiFi网络失败问题排查

解决Android WiFi连接未配置网络的问题

我来帮你一步步排查和解决你遇到的三个核心问题:

1. 为什么ScanResult的networkId会报错?

你一开始用ScanResult.networkId连接WiFi时出错,是因为这个字段只对系统中已保存的配置网络有效。扫描到的未配置WiFi,系统还没给它分配networkId,直接调用自然会报错。正确的逻辑是:先把目标WiFi的配置信息添加到系统的已配置网络列表,再用新生成的networkId去连接。

2. 修复NullPointerException(Context为空)

你修改后的代码里,WiFiList类的init()connect()方法直接调用getActivity(),但这个方法在自定义类中没有正确绑定Activity实例,导致获取到的Context为空。解决办法是:

  • WiFiList类中添加构造方法,接收Activity实例作为参数并保存
  • 所有需要Context的地方,都用这个保存的Activity实例来获取系统服务

修改WiFiList类的核心代码:

class WiFiList {
    protected WifiManager wifiManager;
    protected List<ScanResult> scanList;
    protected ArrayList<WiFiListItem> items;
    protected boolean bScanning = false;
    protected Activity act; // 保存Activity实例

    // 修改构造方法,接收Activity参数
    WiFiList(Activity activity) {
        items = new ArrayList<WiFiListItem>();
        this.act = activity; // 绑定Activity实例
    }

    void init() {
        // 用保存的act实例获取WifiManager
        wifiManager = (WifiManager) act.getSystemService(Context.WIFI_SERVICE);
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        // 注册广播接收器时用act实例
        act.registerReceiver(new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                println("WiFiList: scan finished");
                scanList = wifiManager.getScanResults();
                for (ScanResult networkDevice : scanList) {
                    updateItem(networkDevice.SSID, networkDevice.level);
                }
                bScanning = false;
                wifiScanFinished();
            }
        } , filter);
    }

    // 修改connect方法里的WifiManager获取方式
    void connect() {
        wifiManager = (WifiManager) act.getSystemService(Context.WIFI_SERVICE);
        // ... 后续代码不变
    }
}

然后在setup()里初始化WiFiList时传入Activity实例:

void setup() {
    size(displayWidth, displayHeight, P2D);
    orientation(PORTRAIT);
    // 传入当前Activity实例
    wifiList = new WiFiList(this.getActivity());
    wifiList.init();
    wifiNetworks = wifiList.getItems();
    fontSize = height/30;
    textSize(fontSize);
    textAlign(LEFT, TOP);
    noStroke();
}

3. 解决无法连接未配置WiFi的问题

你当前的connect()方法里,WiFi配置有几个错误,导致无法正确连接:

  • 密钥管理类型设置错误:如果是WPA/WPA2-PSK网络,应该用KeyMgmt.WPA_PSK,而不是KeyMgmt.NONE
  • 同时设置了WEP和WPA的参数,导致配置冲突
  • 添加网络后直接遍历已配置网络,可能无法立即获取到刚添加的配置,最好直接使用addNetwork()返回的networkId

修改后的connect()方法:

void connect() {
    wifiManager = (WifiManager) act.getSystemService(Context.WIFI_SERVICE);
    String targetSSID = "test";
    String targetPass = "testtest";

    WifiConfiguration conf = new WifiConfiguration();
    // SSID必须用双引号包裹
    conf.SSID = "\"" + targetSSID + "\"";
    // 针对WPA2-PSK网络的配置
    conf.preSharedKey = "\"" + targetPass + "\"";
    conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    // 启用必要的加密方式
    conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);

    // 添加网络并获取返回的networkId
    int networkId = wifiManager.addNetwork(conf);
    if (networkId != -1) {
        // 先断开当前连接
        wifiManager.disconnect();
        // 启用目标网络
        boolean enabled = wifiManager.enableNetwork(networkId, true);
        // 重新连接
        boolean reconnected = wifiManager.reconnect();
        println("Connecting to " + targetSSID + ", enabled: " + enabled + ", reconnected: " + reconnected);
    } else {
        println("Failed to add network configuration");
    }
}

额外注意事项

  1. 确保你的应用已经申请了必要的权限,在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 6.0+ 扫描WiFi需要位置权限 -->

Android 6.0及以上版本还需要动态申请位置权限,否则扫描WiFi会失败。

  1. 建议把connect()方法放在扫描完成之后调用(比如在wifiScanFinished()方法里触发),而不是在mousePressed时同时调用scan()connect()——因为扫描是异步操作,直接调用connect()可能扫描结果还没返回。

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

火山引擎 最新活动