我希望设计一个应用程序,它可以显示可用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();
CHANGE_WIFI_STATE
权限。 - ThomasWWifiConfiguration 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();
}
};
请注意,在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 Level 29开始,WifiManager.enableNetwork()
方法被废弃。根据Android API文档(查看此处):
- 请参阅WifiNetworkSpecifier.Builder#build(),了解连接到Wi-Fi网络的新机制。
- 请参阅addNetworkSuggestions(java.util.List)、removeNetworkSuggestions(java.util.List),以获取添加WiFi网络并在自动连接WiFi时考虑的新API。兼容性注意事项:对于目标版本为Build.VERSION_CODES.Q或更高版本的应用程序,此API将始终返回false。
从API Level 29开始,要连接到WiFi网络,您需要使用WifiNetworkSpecifier
。您可以在https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build()上找到示例代码。
我费尽心思才理解为什么你的WPA/WPA2答案不起作用...经过数小时的尝试,我发现了你所遗漏的内容:
conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
对于WPA网络,此项为必需!!!
现在,它可以工作:)
设置权限:
<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;
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()无法断开当前网络连接, 因此无法重新连接到指定的网络。 我已修改上述代码。 对我而言,下面的代码完美地工作:
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);
UID nnnnn没有权限更新配置xxxx。MD_START_CONNECT但没有请求和连接,但应用程序没有足够的权限,因此退出。
- Luis A. Florit获取WiFi列表,连接WiFi(适用于Android版本小于等于9和大于等于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);
}
}
}
}