我想设计一个应用程序,显示可用的Wi-Fi网络列表,并连接到用户选择的任何网络。

我已经实现了显示扫描结果的部分。现在我想连接到用户从扫描结果列表中选择的特定网络。

我怎么做呢?


当前回答

在API级别29中,WifiManager.enableNetwork()方法已弃用。根据Android API文档(点击这里查看):

请参阅WifiNetworkSpecifier.Builder#build()了解触发连接到Wi-Fi网络的新机制。 参见addnetworkrecommendations (java.util.List), removenetworkrecommendations (java.util.List)获取添加Wi-Fi的新API 当自动连接到wifi时,考虑网络。兼容性 注意:对于以Build.VERSION_CODES为目标的应用程序。Q或以上,这个 API总是返回false。

从API级别29开始,要连接到WiFi网络,您将需要使用WifiNetworkSpecifier。您可以在https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build(上找到示例代码)

其他回答

试试这个方法。这很简单:

public static boolean setSsidAndPassword(Context context, String ssid, String ssidPassword) {
    try {
        WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
        Method getConfigMethod = wifiManager.getClass().getMethod("getWifiApConfiguration");
        WifiConfiguration wifiConfig = (WifiConfiguration) getConfigMethod.invoke(wifiManager);

        wifiConfig.SSID = ssid;
        wifiConfig.preSharedKey = ssidPassword;

        Method setConfigMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
        setConfigMethod.invoke(wifiManager, wifiConfig);

        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

在API级别29中,WifiManager.enableNetwork()方法已弃用。根据Android API文档(点击这里查看):

请参阅WifiNetworkSpecifier.Builder#build()了解触发连接到Wi-Fi网络的新机制。 参见addnetworkrecommendations (java.util.List), removenetworkrecommendations (java.util.List)获取添加Wi-Fi的新API 当自动连接到wifi时,考虑网络。兼容性 注意:对于以Build.VERSION_CODES为目标的应用程序。Q或以上,这个 API总是返回false。

从API级别29开始,要连接到WiFi网络,您将需要使用WifiNetworkSpecifier。您可以在https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build(上找到示例代码)

感谢@raji-ramamoorthi和@kenota

对我有效的解决方案是在这个线程中结合以上贡献者。

获取ScanResult的过程如下。

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled() == false) {
            Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show();
            wifi.setWifiEnabled(true);
        }

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent intent) {
                 wifi.getScanResults();
            }
        };

注意在onPause和onStop上取消注册。

public void connectWiFi(ScanResult scanResult) {
        try {

            Log.v("rht", "Item clicked, SSID " + scanResult.SSID + " Security : " + scanResult.capabilities);

            String networkSSID = scanResult.SSID;
            String networkPass = "12345678";

            WifiConfiguration conf = new WifiConfiguration();
            conf.SSID = "\"" + networkSSID + "\"";   // Please note the quotes. String should contain ssid in quotes
            conf.status = WifiConfiguration.Status.ENABLED;
            conf.priority = 40;

            if (scanResult.capabilities.toUpperCase().contains("WEP")) {
                Log.v("rht", "Configuring WEP");    
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

                if (networkPass.matches("^[0-9a-fA-F]+$")) {
                    conf.wepKeys[0] = networkPass;
                } else {
                    conf.wepKeys[0] = "\"".concat(networkPass).concat("\"");
                }

                conf.wepTxKeyIndex = 0;

            } else if (scanResult.capabilities.toUpperCase().contains("WPA")) {
                Log.v("rht", "Configuring WPA");

                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

                conf.preSharedKey = "\"" + networkPass + "\"";

            } else {
                Log.v("rht", "Configuring OPEN network");
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.clear();
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            }

            WifiManager wifiManager = (WifiManager) WiFiApplicationCore.getAppContext().getSystemService(Context.WIFI_SERVICE);
            int networkId = wifiManager.addNetwork(conf);

            Log.v("rht", "Add result " + networkId);

            List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
            for (WifiConfiguration i : list) {
                if (i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
                    Log.v("rht", "WifiConfiguration SSID " + i.SSID);

                    boolean isDisconnected = wifiManager.disconnect();
                    Log.v("rht", "isDisconnected : " + isDisconnected);

                    boolean isEnabled = wifiManager.enableNetwork(i.networkId, true);
                    Log.v("rht", "isEnabled : " + isEnabled);

                    boolean isReconnected = wifiManager.reconnect();
                    Log.v("rht", "isReconnected : " + isReconnected);

                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

如果你的设备知道Wifi配置(已经存储),我们可以跳过火箭科学。只需循环配置,检查SSID是否匹配。如果是,连接并返回。

设置权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

连接:

    try {
    String ssid = null;
    if (wifi == Wifi.PCAN_WIRELESS_GATEWAY) {
        ssid = AesPrefs.get(AesConst.PCAN_WIRELESS_SSID,
                context.getString(R.string.pcan_wireless_ssid_default));
    } else if (wifi == Wifi.KJ_WIFI) {
        ssid = context.getString(R.string.remote_wifi_ssid_default);
    }

    WifiManager wifiManager = (WifiManager) context.getApplicationContext()
            .getSystemService(Context.WIFI_SERVICE);

    List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();

    for (WifiConfiguration wifiConfiguration : wifiConfigurations) {
        if (wifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
            wifiManager.enableNetwork(wifiConfiguration.networkId, true);
            Log.i(TAG, "connectToWifi: will enable " + wifiConfiguration.SSID);
            wifiManager.reconnect();
            return null; // return! (sometimes logcat showed me network-entries twice,
            // which may will end in bugs)
        }
    }
} catch (NullPointerException | IllegalStateException e) {
    Log.e(TAG, "connectToWifi: Missing network configuration.");
}
return null;

获取Wifi列表,连接Wifi (Android <=9 and Android >=10)

[assembly: Xamarin.Forms.Dependency(typeof(WifiService))]
namespace configurator.Droid.Services
{
   public class WifiService : IWifiService
 {
    private bool _requested;
    private bool _statusConnect;

    private NetworkCallback _callback;
    private Context _context = null;
    private Version _version;
    private WifiManager _wifiManager = null;
    private ConnectivityManager _connectivityManager;
    private WifiConfiguration _config;
    private int _temp = -1;

    public WifiService()
    {
        this._context = Android.App.Application.Context;
        _version = DeviceInfo.Version;
        _wifiManager = _context.GetSystemService(Context.WifiService) as WifiManager;
    }

    [Obsolete]
    public async Task<bool> ConnectToWifiAsync(string ssid, string password, Action<bool> animation = null)
    {
        if (!_wifiManager.IsWifiEnabled)
        {
            if (_version.Major >= 9)
            {
                bool result =  await Device.InvokeOnMainThreadAsync(async () => await Application.Current.MainPage.DisplayAlert("", "The program requires accesss to Wi-Fi. Turn on Wi-fi?", "Ok", "Cancel")) ;

                if (!result)
                {
                    return false;
                }

                Intent intent;

                if (_version.Major == 9)
                {
                    intent = new Intent(Android.Provider.Settings.ActionWifiSettings);
                }
                else
                {
                    intent = new Intent(Android.Provider.Settings.Panel.ActionInternetConnectivity);
                }

                intent.AddFlags(ActivityFlags.NewTask);
                Android.App.Application.Context.StartActivity(intent);
            }
            else
            {
                _wifiManager.SetWifiEnabled(true);
            }
        }
        else
        {

            if (_version.Major <= 9 && _version.Major >= 8)
            {
                await Device.InvokeOnMainThreadAsync(async () => await Geolocation.GetLastKnownLocationAsync());
                JoinToWifiLessAndroidQAsync(ssid, password, animation);
            }
            else if(_version.Major < 8)
            {
                JoinToWifiLessAndroidQAsync(ssid, password, animation);
            }
            else
            {
                await Device.InvokeOnMainThreadAsync(async () => await Geolocation.GetLastKnownLocationAsync());
                await JoinToWifiMoreAndroidPie(ssid, password);
            }
        }
        
        return await Task.FromResult(_statusConnect);
    }

    [Obsolete]
    public async Task<IEnumerable<string>> GetAvailableNetworksAsync()
    {
        
        IEnumerable<string> availableNetworks = null;

        // Get a handle to the Wifi
        if (!_wifiManager.IsWifiEnabled)
            _wifiManager.SetWifiEnabled(true);
        var wifiReceiver = new WifiReceiver(_wifiManager);

        await Task.Run(() =>
        {
            // Start a scan and register the Broadcast receiver to get the list of Wifi Networks
            _context.RegisterReceiver(wifiReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
            availableNetworks = wifiReceiver.Scan();
        });

        return availableNetworks;
    }

    private class NetworkCallback : ConnectivityManager.NetworkCallback
    {
        private ConnectivityManager _connectivityManager;

        public NetworkCallback(ConnectivityManager connectivityManager)
        {
            _connectivityManager = connectivityManager;
        }
        public Action<Network> NetworkAvailable { get; set; }
        public Action NetworkUnavailable { get; set; }

        public override void OnAvailable(Network network)
        {
            _connectivityManager.BindProcessToNetwork(network);
            base.OnAvailable(network);
            NetworkAvailable?.Invoke(network);
        }

        public override void OnUnavailable()
        {
            base.OnUnavailable();
            NetworkUnavailable?.Invoke();
        }
    }

    [BroadcastReceiver(Enabled = true, Exported = false)]
    class WifiReceiver : BroadcastReceiver
    {
        private WifiManager _wifi;
        private List<string> _wifiNetworks;
        private AutoResetEvent _receiverARE;
        private Timer _tmr;
        private const int TIMEOUT_MILLIS = 20000; // 20 seconds timeout

        public WifiReceiver()
        {

        }

        public WifiReceiver(WifiManager wifi)
        {
            this._wifi = wifi;
            _wifiNetworks = new List<string>();
            _receiverARE = new AutoResetEvent(false);
        }

        [Obsolete]
        public IEnumerable<string> Scan()
        {
            _tmr = new Timer(Timeout, null, TIMEOUT_MILLIS, System.Threading.Timeout.Infinite);
            _wifi.StartScan();
            _receiverARE.WaitOne();
            return _wifiNetworks;
        }

        public override void OnReceive(Context context, Intent intent)
        {
            IList<ScanResult> scanwifinetworks = _wifi.ScanResults;
            foreach (ScanResult wifinetwork in scanwifinetworks)
            {
                _wifiNetworks.Add(wifinetwork.Ssid);
            }

            _receiverARE.Set();
        }

        private void Timeout(object sender)
        {
            // NOTE release scan, which we are using now, or we throw an error?
            _receiverARE.Set();
        }
    }

    [Obsolete]
    private void JoinToWifiLessAndroidQAsync(string ssid, string password, Action<bool> animation)
    {
        animation?.Invoke(true);

        _config = new WifiConfiguration
        {
            Ssid = "\"" + ssid + "\"",
            PreSharedKey = "\"" + password + "\""
        };

        try
        {
            _temp = _wifiManager.AddNetwork(_config);
            _wifiManager.Disconnect();
            var result = _wifiManager.EnableNetwork(_temp, true);
            _wifiManager.Reconnect();

            int i = 0;

            do
            {
                Thread.Sleep(2000);
                //wait connection
                i++;
                if (i == 7)
                    break;

            } while (GetCurrentConnectName() != ssid);

            Thread.Sleep(6000);

            if (i == 7)
            {
                throw new Exception("Connect to PC failed. Long time connect(14000ms)");
            }
            else
            {
                _statusConnect = true;
            }                
        }
        catch (Exception ex)
        {
            Helpers.Logger.Error($"{nameof(WifiService)}||JoinToWifiLessAndroidQ||{ex.Message}");
            _statusConnect = false;
        }
    }

    [Obsolete]
    private async Task<bool> JoinToWifiMoreAndroidPie(string ssid, string password)
    {
        var specifier = new WifiNetworkSpecifier.Builder()
                       .SetSsid(ssid)
                       .SetWpa2Passphrase(password)
                       .Build();
                      
        var request = new NetworkRequest.Builder()
                       .AddTransportType(TransportType.Wifi) 
                       .RemoveCapability(NetCapability.Internet) 
                       .SetNetworkSpecifier(specifier) 
                       .Build();

        _connectivityManager = _context.GetSystemService(Context.ConnectivityService) as ConnectivityManager;

        if (_requested)
        {
            _connectivityManager.UnregisterNetworkCallback(_callback);
        }

        bool confirmConnect = false;

        _callback = new NetworkCallback(_connectivityManager)
        {
            NetworkAvailable = network =>
            {
                // we are connected!
                _statusConnect = true;
                confirmConnect = true;
            },
            NetworkUnavailable = () =>
            {
                _statusConnect = false;
                confirmConnect = true;
            }
        };

        _connectivityManager.RequestNetwork(request, _callback);
        _requested = true;

        do
        {
            //wait callback
            await Task.Delay(TimeSpan.FromSeconds(5));
            Helpers.Logger.Info($"{nameof(WifiService)}||JoinToWifiMoreAndroidPie||Waiting callback....");

        } while (!confirmConnect);

        return await Task.FromResult(true);
    }

    public string GetCurrentConnectName()
    {
        WifiInfo wifiInfo = _wifiManager.ConnectionInfo;
        if (wifiInfo.SupplicantState == SupplicantState.Completed)
        {
            char[] chars = {'\"'};
            var masChar = wifiInfo.SSID.Trim(chars);
            return masChar;
        }
        else
        {
            return null;
        }
    }

    [Obsolete]
    public async Task ReconnectToWifi()
    {
        if (_version.Major > 9)
        {
            _connectivityManager.UnregisterNetworkCallback(_callback);
            await Task.Delay(10000);
            var network = _connectivityManager.ActiveNetwork;

            if(network == null)
            {
                var dataNetwork = await ManagerSecureStorage.GetConnectedNetworkInfo();
                await JoinToWifiMoreAndroidPie(dataNetwork["NetName"], dataNetwork["Password"]);
            }
            else
            {
                _connectivityManager.BindProcessToNetwork(network);
            }
        }
        else
        {
            if(_temp == -1)
            {
                var temp = _wifiManager.ConfiguredNetworks;
                _temp = temp.Last().NetworkId;
            }
            
            _wifiManager.RemoveNetwork(_temp);
            _wifiManager.Reconnect();
            await Task.Delay(10000);
        }
    }
  }
}