我想设计一个应用程序,显示可用的Wi-Fi网络列表,并连接到用户选择的任何网络。
我已经实现了显示扫描结果的部分。现在我想连接到用户从扫描结果列表中选择的特定网络。
我怎么做呢?
你需要像这样创建WifiConfiguration实例:
WifiConfiguration
String networkSSID = "test"; String networkPass = "pass"; WifiConfiguration conf = new WifiConfiguration(); conf.SSID = "\"" + networkSSID + "\""; // Please note the quotes. String should contain ssid in quotes
然后,对于WEP网络,你需要这样做:
conf.wepKeys[0] = "\"" + networkPass + "\""; conf.wepTxKeyIndex = 0; conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
对于WPA网络,您需要添加这样的密码短语:
conf.preSharedKey = "\""+ networkPass +"\"";
对于开放网络,你需要这样做:
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
然后,你需要将其添加到Android wifi管理器设置:
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); wifiManager.addNetwork(conf);
最后,你可能需要启用它,所以Android连接到它:
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks(); for( WifiConfiguration i : list ) { if(i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) { wifiManager.disconnect(); wifiManager.enableNetwork(i.networkId, true); wifiManager.reconnect(); break; } }
UPD:在WEP的情况下,如果您的密码是十六进制,您不需要用引号包围它。
早一点回答有用,但解决方案实际上可以更简单。循环通过配置的网络列表是不需要的,因为当你通过WifiManager添加网络时,你会得到网络id。
所以完整、简化的解决方案应该是这样的:
WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = String.format("\"%s\"", ssid); wifiConfig.preSharedKey = String.format("\"%s\"", key); WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE); //remember id int netId = wifiManager.addNetwork(wifiConfig); wifiManager.disconnect(); wifiManager.enableNetwork(netId, true); wifiManager.reconnect();
在连接WIFI网络之前,您需要检查WIFI网络的安全类型ScanResult类有一个功能。该字段提供网络类型
参考:https://developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities
WIFI网络有三种类型。
首先,实例化一个wificconfiguration对象并填写网络的SSID(注意它必须用双引号括起来),将初始状态设置为禁用,并指定网络的优先级(40左右的数字似乎工作得很好)。
WifiConfiguration wfc = new WifiConfiguration(); wfc.SSID = "\"".concat(ssid).concat("\""); wfc.status = WifiConfiguration.Status.DISABLED; wfc.priority = 40;
wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); wfc.allowedAuthAlgorithms.clear(); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
对于使用WEP的网络;注意WEP密钥也包含在双引号中。
wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); if (isHexString(password)) wfc.wepKeys[0] = password; else wfc.wepKeys[0] = "\"".concat(password).concat("\""); wfc.wepTxKeyIndex = 0;
对于使用WPA和WPA2的网络,我们可以为其中任何一个设置相同的值。
wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wfc.preSharedKey = "\"".concat(password).concat("\"");
最后,我们可以将该网络添加到WifiManager的已知列表中
WifiManager wfMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); int networkId = wfMgr.addNetwork(wfc); if (networkId != -1) { // success, can call wfMgr.enableNetwork(networkId, true) to connect }
你需要子类化这个活动并实现它的方法:
public class SampleActivity extends WifiBaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected int getSecondsTimeout() { return 10; } @Override protected String getWifiSSID() { return "WifiNetwork"; } @Override protected String getWifiPass() { return "123456"; } }
归功于@raji-ramamoorthi &@kenota
对我有效的解决方案是在这个线程中结合以上贡献者。
得到ScanResult的过程如下。
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(); } };
注意unregister它在onPause &onStop活这个unregisterReceiver(broadcastReceiver);
unregister
onPause
onStop
unregisterReceiver(broadcastReceiver);
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(); } }
试试这个方法。这很简单:
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; } }
如果你的设备知道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;
我绞尽脑汁才明白为什么你的WPA/WPA2答案不管用……经过几个小时的尝试,我找到了你所缺少的:
conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
需要WPA网络!!!!
现在,它工作了:)
我也尝试连接到网络。 以上提出的解决方案都不适用于hugerock t70。 wifiManager.disconnect()函数;不断开当前网络。 Аnd因此不能重新连接到指定的网络。 我修改了上面的代码。 对我来说,代码bolow工作完美:
String networkSSID = "test"; String networkPass = "pass"; WifiConfiguration conf = new WifiConfiguration(); conf.SSID = "\"" + networkSSID + "\""; conf.wepKeys[0] = "\"" + networkPass + "\""; conf.wepTxKeyIndex = 0; conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); conf.preSharedKey = "\""+ networkPass +"\""; WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); int networkId = wifiManager.addNetwork(conf); wifi_inf = wifiManager.getConnectionInfo(); /////important!!! wifiManager.disableNetwork(wifi_inf.getNetworkId()); ///////////////// wifiManager.enableNetwork(networkId, true);
在API级别29中,WifiManager.enableNetwork()方法是弃用。根据Android API文档(检查在这里):
WifiManager.enableNetwork()
请参阅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建立()找到示例代码
WifiNetworkSpecifier
获取Wifi列表,连接到Wifi (Android <=9和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); } } } }