如何以编程方式连接到 Android 中的特定 Wi-Fi 网络?
Posted
技术标签:
【中文标题】如何以编程方式连接到 Android 中的特定 Wi-Fi 网络?【英文标题】:How do I connect to a specific Wi-Fi network in Android programmatically? 【发布时间】:2012-02-07 18:01:27 【问题描述】:我想设计一个显示可用 Wi-Fi 网络列表并连接到用户选择的任何网络的应用。
我已经实现了显示扫描结果的部分。现在我想连接到用户从扫描结果列表中选择的特定网络。
我该怎么做?
【问题讨论】:
相关:"How to programatically create and read WEP/EAP WiFi configurations in android?" 这对我有用 WPA2 和 WEP:***.com/a/29575563/7337517 【参考方案1】:您需要像这样创建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 的情况下,如果您的密码是十六进制的,则不需要用引号括起来。
【讨论】:
效果很好!谢谢 :) 但我还想问一件事。不需要设置 allowedPairwiseCipher、allowedAuthALgorithms 和 allowedProtocols 吗?以及如何决定设置哪个特定属性;像您为 WEP 网络设置 GroupCipher 的 WEP40 吗? 我忘了提一件事。在 WEP 的情况下,如果您的密码是十六进制的,则不需要用引号括起来。 感谢您的出色解决方案,您能否详细说明如何检查连接是否成功。例如,用户可能输入了错误的密码并且应该得到通知。 如果所需的 Wifi 热点根本不使用任何密码,我们应该使用 .preSharedKey = null 吗?或者我们应该设置 .preSharedKey = "";哪一个是正确的? @kenota 它对我不起作用:它会直接重新连接到以前记住的 wifi,而不是连接到新的。【参考方案2】:earlier answer works,但解决方案实际上可以更简单。当您通过 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();
【讨论】:
如果没有使用密码。我们应该把 .preSharedKey = null;还是我们应该只放空字符串@seanloyola? @MuhammedRefaat 你断开连接,以防你已经连接到另一个网络。 @gumuruh 如果不需要密钥,您根本不必包含 presharedkey 对象。 根据 enableNetwork 的 javadoc,如果你使用 boolean disableOthers true,那么你不必断开或连接,它会为你做这两件事 应该提到需要CHANGE_WIFI_STATE
权限。【参考方案3】:
在连接 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
【讨论】:
关于优先级的说明,在我的电话号码上大约 4000 个有效。最好使该部分更具动态性(迭代现有配置等) 如何从 SSID 获取网络安全类型以进行 wifi ScanResult @shantanu 查看以下详情。 ***.com/questions/6866153/… 在三星设备上,密码是散列字符串。并且代码不起作用。你检查了吗? 密码长度也需要大于 8 否则 wfMgr.addNetwork(wfc) 将返回 -1。此外,SSID 不应在预配置的网络列表中,否则 addNetwork() 将返回 -1【参考方案4】:感谢@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();
【讨论】:
【参考方案5】:在 API 级别 29 中,WifiManager.enableNetwork()
方法已弃用。根据 Android API 文档(检查here):
有关触发连接到 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()找到示例代码
【讨论】:
是否可以使用新的 WifiNetWorkSpecifier.Builder 连接到 WEP 网络?我找不到向构建器添加 WEP 密码的方法。 1 号似乎不起作用,是否有任何回调? #1 也不行,设备提示连接网络,但没有网络连接。根据文档:“这些说明符只能用于请求本地 wifi 网络(即没有互联网功能)。” - 我无法让#2 做任何事情,只是显示一个带有“?”的 wifi 图标。 有什么方法可以使用这个方法,切换网络和not prompt a user
?【参考方案6】:
如果您的设备知道 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;
【讨论】:
【参考方案7】:我想明白为什么你对 WPA/WPA2 的回答不起作用......经过数小时的尝试后,我发现你缺少什么:
conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
对于 WPA 网络是必需的!!!!
现在,它可以工作了:)
【讨论】:
【参考方案8】:这是一个您可以子类化以强制连接到特定 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";
【讨论】:
link down 能给个新的吗?【参考方案9】:我也尝试连接到网络。 以上提出的解决方案均不适用于 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);
【讨论】:
我在 Android 10 中遇到错误:UID nnnnn does not have permission to update configuration xxxx. MD_START_CONNECT but no requests and connected, but app does not have sufficient permissions, bailing.
谢谢!使用带有 Android 8.1 的阿尔卡特 5041C 为我工作。您可以看到它在连接到新的 wifi 之前与当前 wifi 断开连接【参考方案10】:
获取 Wifi 列表,连接到 Wifi(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();
【讨论】:
【参考方案11】:试试这个方法。很简单:
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;
【讨论】:
以上是关于如何以编程方式连接到 Android 中的特定 Wi-Fi 网络?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式连接到已在 Android 手机中设置的 ***
如何以编程方式在 android 中创建 *** 配置文件并连接到它?