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

如何在NativeScript中自动切换同SSID多BSSID的最强WiFi接入点?

解决WiFi自动切换同SSID最强接入点的问题

我仔细看了你的代码和问题描述,发现几个核心问题导致程序无法触发切换到更强的接入点,下面是诊断和修复方案:


问题根源分析

  1. ScanResult的networkId无效:你从scanResults.get(n).networkId获取的ID是没用的——Android的ScanResult对象里的networkId是预留字段,实际值通常为-1,根本不是系统中已配置WiFi的有效网络ID,这直接导致后续的updateNetwork和enableNetwork操作完全失效。
  2. 未正确断开当前连接:切换时没有先禁用当前的WiFi连接,直接调用enableNetwork无法强制系统切换接入点。
  3. WiFi配置逻辑错误:你直接用扫描结果构建WifiConfiguration,但正确的做法应该是先找到系统中已配置的同SSID网络,再修改其目标BSSID,这样才能让系统识别要切换的接入点。
  4. 扫描结果判断逻辑错误:startScan()返回的是“扫描是否发起成功”,不是“扫描结果是否可用”,你用它来判断是否处理结果会漏掉很多有效扫描数据。

修复后的完整代码

import { Injectable, NgZone } from '@angular/core';
import * as applicationModule from 'tns-core-modules/application';
import * as utils from 'tns-core-modules/utils/utils';
import { config } from '../data/config';
import { WifiCon } from '../interfaces/wifi-con';
import { LoggerService } from './logger.service';

declare var android: any;

@Injectable({
  providedIn: 'root'
})
export class WifiConService implements WifiCon {
  readonly ssid: string = config.SSID;
  readonly password: string = '12345678';
  private currentConnectedBSSID = '';
  private readonly wifiManager: any;
  private readonly items: Array<Item> = new Array<Item>();

  constructor(private readonly zone: NgZone, private readonly logger: LoggerService) {
    this.wifiManager = utils.ad.getApplicationContext()
      .getSystemService(android.content.Context.WIFI_SERVICE);
    this.monitorBSSID();
    this.logger.log('Created service for wifi');
  }

  // 初始化或获取已配置的WiFi网络
  private getOrCreateConfiguredNetwork(): android.net.wifi.WifiConfiguration | null {
    const configuredNetworks = this.wifiManager.getConfiguredNetworks();
    if (!configuredNetworks) return null;

    // 查找已配置的同SSID网络
    for (let i = 0; i < configuredNetworks.size(); i++) {
      const network = configuredNetworks.get(i);
      if (network.SSID === `"${this.ssid}"`) {
        return network;
      }
    }

    // 如果没有配置过,创建新的配置
    const conf = new android.net.wifi.WifiConfiguration();
    conf.SSID = `"${this.ssid}"`;
    conf.preSharedKey = `"${this.password}"`;
    const netId = this.wifiManager.addNetwork(conf);
    this.wifiManager.saveConfiguration();
    return this.wifiManager.getConfiguredNetworks().find(net => net.networkId === netId);
  }

  connectWiFiNetwork(): void {
    if (this.items.length === 0) {
      this.logger.log('No available access points for target SSID');
      return;
    }

    // 按信号强度降序排序
    this.items.sort((a, b) => b.strength - a.strength);
    const strongestAP = this.items[0];

    // 如果当前已经连接到最强AP,无需切换
    if (strongestAP.bssid === this.currentConnectedBSSID) {
      this.logger.log(`Already connected to strongest AP: ${strongestAP.bssid}`);
      return;
    }

    this.logger.log(`Switching to stronger AP: ${strongestAP.bssid} (strength: ${strongestAP.strength})`);

    // 获取已配置的网络
    const configuredNetwork = this.getOrCreateConfiguredNetwork();
    if (!configuredNetwork) {
      this.logger.log('Failed to get or create configured network');
      return;
    }

    // 修改配置,指定要连接的BSSID
    configuredNetwork.BSSID = strongestAP.bssid;
    const updatedNetId = this.wifiManager.updateNetwork(configuredNetwork);
    this.wifiManager.saveConfiguration();

    // 先断开当前连接
    this.wifiManager.disconnect();

    // 启用目标网络并重新连接
    const isEnabled = this.wifiManager.enableNetwork(updatedNetId, true);
    const isReconnected = this.wifiManager.reconnect();

    this.logger.log(`Switch result: enableNetwork=${isEnabled}, reconnect=${isReconnected}`);
    this.currentConnectedBSSID = strongestAP.bssid;
  }

  disConnectWifi(): boolean {
    this.logger.log(`WiFi disconnected from "${this.ssid}"`);
    this.currentConnectedBSSID = '';
    return this.wifiManager.setWifiEnabled(false);
  }

  getConSubject(): boolean {
    return true;
  }

  switchToStrongNtwk(BSSID: string): boolean {
    return true;
  }

  getNtwkInfo(): any {
    return this.wifiManager.getConnectionInfo();
  }

  isWifiEnabled(): boolean {
    return this.wifiManager.isWifiEnabled();
  }

  monitorBSSID(): void {
    const receiverCallback = (androidContext, intent) => {
      // 检查扫描结果是否可用
      if (!intent.getBooleanExtra(android.net.wifi.WifiManager.EXTRA_RESULTS_UPDATED, false)) {
        this.logger.log('Scan results not updated');
        return;
      }

      this.zone.run(() => {
        this.items.length = 0;
        const scanResults = this.wifiManager.getScanResults();
        const currentConnectionInfo = this.getNtwkInfo();
        this.currentConnectedBSSID = currentConnectionInfo.getBSSID() || '';

        for (let n = 0; n < scanResults.size(); n++) {
          const result = scanResults.get(n);
          if (result.SSID === this.ssid) {
            this.items.push({
              ssid: result.SSID,
              bssid: result.BSSID,
              strength: result.level,
              isConnected: (result.BSSID === this.currentConnectedBSSID),
              // ScanResult的networkId无效,这里不再使用
              netId: -1
            });
          }
        }

        this.logger.log(`Available APs: ${JSON.stringify(this.items)}`);
        this.connectWiFiNetwork();
      });
    };

    applicationModule.android.registerBroadcastReceiver(
      android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION,
      receiverCallback
    );

    setInterval(() => {
      this.logger.log('Initiating WiFi scan');
      // startScan返回的是扫描是否发起,不是结果是否可用
      const scanInitiated = this.wifiManager.startScan();
      this.logger.log(`Scan initiated: ${scanInitiated}`);
    }, config.wifi_scan_time * 1000);
  }
}

interface Item {
  ssid: string;
  bssid: string;
  strength: number;
  isConnected: boolean;
  netId: number;
}

关键修改点说明

  1. 修复无效networkId问题:移除了从ScanResult获取networkId的逻辑,改用getOrCreateConfiguredNetwork()方法获取系统中已配置的同SSID网络ID,这个ID才是真正有效的。
  2. 正确处理扫描结果:在广播接收器中使用EXTRA_RESULTS_UPDATED来判断扫描结果是否更新,不再依赖startScan()的返回值。
  3. 强制断开并切换:切换前先调用disconnect()断开当前连接,再启用目标网络并调用reconnect(),确保系统强制切换到指定的BSSID。
  4. 优化配置更新逻辑:先查找已有的配置,避免重复创建;更新配置后调用saveConfiguration()确保修改生效。
  5. 增加状态判断:切换前检查是否已经连接到最强AP,避免不必要的切换操作,减少资源消耗。

这样修改后,你的程序应该能正确识别最强信号的接入点,并自动触发切换了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 13:12:48