如何以编程方式连接到Android中的特定Wi-Fi网络?


294

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

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

我该怎么做呢?



这为我WPA2和WEP工作:stackoverflow.com/a/29575563/7337517
昆丹

Answers:


440

您需要创建这样的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,如果您的密码为十六进制,则无需用引号引起来。


5
效果很好!谢谢:)但我想问一件事。您是否不需要设置allowedPairwiseCipher,allowedAuthALgorithms和allowedProtocols?以及如何决定要设置哪个特定属性;就像您为WEP网络的GroupCipher设置了WEP40一样?
Vikram Gupta 2012年

8
我忘了提一件事。对于WEP,如果您的密码为十六进制,则无需用引号引起来。
kenota 2012年

8
感谢您提供的不错的解决方案,您能否详细说明如何检查连接是否成功。例如,用户可能输入了错误的密码,并且应该收到有关该密码的通知。
Pascal Klein 2013年

3
如果所需的Wifi热点根本不使用任何密码怎么办...。我们应该使用.preSharedKey = null; 还是应该设置.preSharedKey =“”; 哪一个是正确的?@kenota
gumuruh 2014年

6
它对我不起作用:它确实直接重新连接到以前记住的wifi,而不是连接到新的wifi。
Virthuss '16

138

刚才的答复工作,但解决的办法其实是可以更简单。通过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();

1
如果未使用密码。我们应该把.preSharedKey = null;吗?还是我们应该放空字符串@seanloyola?
gumuruh 2014年

2
如果您已经连接到另一个网络,则@MuhammedRefaat会断开连接。
肖恩·洛伊奥拉2014年

1
@gumuruh如果不需要密钥,则根本不必包括presharedkey对象。
肖恩·洛伊奥拉2014年

7
根据enableNetwork的javadoc,如果您使用boolean disableOthers true,那么您不必断开连接或连接,它将为您做到这一切
NikkyD

12
应该提到的CHANGE_WIFI_STATE是需要许可。
ThomasW

27

在连接WIFI网络之前,您需要检查WIFI网络的安全性类型ScanResult类是否具有功能。该字段为您提供网络类型

请参阅:https : //developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities

共有三种类型的WIFI网络。

首先,实例化一个WifiConfiguration对象并填写网络的SSID(注意,必须用双引号将其括起来),将初始状态设置为Disabled,然后指定网络的优先级(大约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个有效。可能最好使该部分更具动态性(迭代现有配置等)
2015年

我如何从SSID获取wifi ScanResult的网络安全类型
shantanu 2015年

@shantanu检查以下详细信息。stackoverflow.com/questions/6866153/...
Kalpesh Gohel

在三星设备上,密码是哈希字符串。而且代码不起作用。你检查了吗?
Nguyen Minh Binh,

您可以提供一个示例来连接sim类型wifi的EAP吗?
Prashanth Debbadwar '16

19

归功于@ 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();
            }
        };

通知unregisteronPauseonStop住这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

如果您的设备知道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;

5

经过数小时的尝试,我发现您所缺少的是为什么让您的WPA / WPA2答案无效?

conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);

WPA网络需要!!!!

现在,它可以工作了:)


4

您可以子类化此活动以强制连接到特定的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";
  }
}

链接下来可以给新的吗?
编码

4

在API级别29中,不赞成使用WifiManager.enableNetwork() method 。按照Android的API文档(请点击这里

  1. 有关触发与Wi-Fi网络的连接的新机制,请参见WifiNetworkSpecifier.Builder#build()。
  2. 请参阅addNetworkSuggestions(java.util.List),removeNetworkSuggestions(java.util.List)中的新API,以添加Wi-Fi网络,以便在自动连接到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密码添加到生成器的方法。
Dieter27

1号似乎不起作用,是否有回调方法?
Faizan Mir

1

我也尝试连接到网络。上面提出的所有解决方案均不适用于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);

我在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.
Luis A. Florit

0

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

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;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.