我想设计一个显示可用 Wi-Fi 网络列表并连接到用户选择的任何网络的应用程序。
我已经实现了显示扫描结果的部分。现在我想连接到用户从扫描结果列表中选择的特定网络。
我该怎么做呢?
我想设计一个显示可用 Wi-Fi 网络列表并连接到用户选择的任何网络的应用程序。
我已经实现了显示扫描结果的部分。现在我想连接到用户从扫描结果列表中选择的特定网络。
我该怎么做呢?
您需要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网络分为三种。
首先,实例化一个 WifiConfiguration 对象并填写网络的 SSID(注意它必须用双引号括起来),将初始状态设置为禁用,并指定网络的优先级(40 左右的数字似乎效果很好)。
WifiConfiguration wfc = new WifiConfiguration();
wfc.SSID = "\"".concat(ssid).concat("\"");
wfc.status = WifiConfiguration.Status.DISABLED;
wfc.priority = 40;
现在来看更复杂的部分:我们需要填充 WifiConfiguration 的几个成员来指定网络的安全模式。对于开放网络。
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
}
感谢@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();
}
};
注意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();
}
}
在 API 级别 29 中,WifiManager.enableNetwork()
方法已弃用。根据 Android API 文档(在此处查看):
- 有关触发连接到 Wi-Fi 网络的新机制,请参阅 WifiNetworkSpecifier.Builder#build()。
- 请参阅 addNetworkSuggestions(java.util.List)、removeNetworkSuggestions(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()找到示例代码
如果您的设备知道 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 网络所必需的!!!!
现在,它起作用了:)
这是您可以子类化以强制连接到特定 wifi 的活动: https ://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java
您需要将此活动子类化并实现其方法:
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";
}
}
我也尝试连接到网络。以上提出的解决方案均不适用于 hugerock t70。函数 wifiManager.disconnect(); 不会断开与当前网络的连接。Аnd 因此无法重新连接到指定的网络。我已经修改了上面的代码。对我来说,下面的代码完美地工作:
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);
获取 Wifi 列表,连接到 Wifi(Android <=9 和 Android >=10)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Android.Content;
using Android.Net;
using Android.Net.Wifi;
using Xamarin.Essentials;
[assembly: Xamarin.Forms.Dependency(typeof(Wifi))]
namespace configurator.Droid.Services
{
public class Wifi : IWifi
{
private NetworkCallback _callback;
private bool _requested;
private Context _context = null;
private WifiManager _wifiManager = null;
private string _statusText;
public Wifi()
{
this._context = Android.App.Application.Context;
}
[Obsolete]
public void ConnectToWifi(string ssid, string password)
{
if (!_wifiManager.IsWifiEnabled)
_wifiManager.SetWifiEnabled(true);
Version version = Xamarin.Essentials.DeviceInfo.Version;
if (version.Major <= 9 && version.Minor < 9)
{
var config = new WifiConfiguration();
config.Ssid = "\"" + ssid + "\"";
config.PreSharedKey = "\"" + password + "\"";
var temp = _wifiManager.AddNetwork(config);
_wifiManager.Disconnect();
_wifiManager.EnableNetwork(temp, true);
_wifiManager.Reconnect();
}
else
{
var specifier = new WifiNetworkSpecifier.Builder()
.SetSsid(ssid)
.SetWpa2Passphrase(password)
.Build();
var request = new NetworkRequest.Builder()
.AddTransportType(TransportType.Wifi) // we want WiFi
.RemoveCapability(NetCapability.Internet) // Internet not required
.SetNetworkSpecifier(specifier) // we want _our_ network
.Build();
var connectivityManager = _context.GetSystemService(Context.ConnectivityService) as ConnectivityManager;
if (_requested)
{
connectivityManager.UnregisterNetworkCallback(_callback);
}
_callback = new NetworkCallback
{
NetworkAvailable = network =>
{
// we are connected!
_statusText = $"Request network available";
},
NetworkUnavailable = () =>
{
_statusText = $"Request network unavailable";
}
};
connectivityManager.RequestNetwork(request, _callback);
_requested = true;
}
}
[Obsolete]
public async Task<IEnumerable<string>> GetAvailableNetworksAsync()
{
var location = await Geolocation.GetLastKnownLocationAsync();
IEnumerable<string> availableNetworks = null;
// Get a handle to the Wifi
_wifiManager =
`(WifiManager)_context.GetSystemService(Context.WifiService);`
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
{
public Action<Network> NetworkAvailable { get; set; }
public Action NetworkUnavailable { get; set; }
public override void OnAvailable(Network 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();
}
}
}
}
试试这个方法。这很容易:
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;
}
}