Sample code for Android to connect anonymous WiFi

  • 2021-11-13 02:35:42
  • OfStack

Preface

Because the development needs to realize wifi connection within the application, it is relatively simple to realize wifi connection combined with online data, but there is little mention of anonymous wifi connection, so share it here.

Basic use

First of all, introduce some basic concepts and tools related to the development of wifi. If you have had contact with wifi, you can skip the next section directly.

1. Permission

In Android to use system function 1, you have to apply for permission. Here, wifi needs the following permissions


 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> //  System permissions required  [ Location authority ]

Because wifi can be used for positioning, it is necessary to apply for positioning authority here. For devices above 6.0, positioning authority needs to be applied actively.

2.API

类名 功能
WifiManager wifi统1管理类,进行各种wifi操作
WifiInfo 描述当前连接的wifi热点信息
WifiConfiguration wifi网络配置信息
ScanResult 描述扫描出的wifi热点的信息

The WifiManager class is the api exposed by the framework layer and is used to manage the wifi.


val mWifiManager = mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

Through it, you can get: 1. List of configured networks. 2. The wifi of the current connection. 3. The scanned wifi. 4. And 1 constants indicate the intention of broadcasting, etc.

ScanResult class is used to store wifi scanning result information, mainly including the following contents:

属性 描述
SSID 描述wifi热点的名称,就是大家搜索到的直接名称,如ChinaNet
BSSID 姑且理解成热点的mac地址,但实际有所不同
networkID 数字型的id
level 描述wifi信号强弱的值,值是负数,绝对值越小,信号越强
capabilities 如加密方式,如WEP

3. Monitor the change of wifi status

The change of wifi state will cause broadcast events to occur.


val filter = IntentFilter()
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION) // Eavesdropping wifi State change 
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) // Monitor and scan wifi List change 

private val mReceiver = object : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
      val action = intent.action
      if (TextUtils.isEmpty(action)) return
      when (action) {
        WifiManager.WIFI_STATE_CHANGED_ACTION -> {
         
        }
        WifiManager.SCAN_RESULTS_AVAILABLE_ACTION -> {
          
        }
      }
    }
  }

There are enum types in the current state in WifiManager, which can be seen in the following table:

名称 描述
WIFI_STATE_DISABLING wifi正在关闭
WIFI_STATE_DISABLED wifi关闭
WIFI_STATE_ENABLING wifi正在开启
WIFI_STATE_ENABLED wifi开启
WIFI_STATE_UNKNOWN wifi未知

Connect the normal wifi

Connecting wifi can be roughly divided into the following steps:

Get the SSID that you want to connect to the WiFi hotspot, the encryption method information, and the password entered by the user Create an wifiConfigruation object based on the above information Call the method of WifiManager, pass in wifiConfigruation, and complete wifi connection

public static void connectNewWifi(Context mContext, WifiConfiguration wifiConfiguration) {
    
    WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    int networkId = wifiManager.addNetwork(wifiConfiguration);
    wifiManager.enableNetwork(networkId, true);

  }

Therefore, the key point is how to create wifiConfigruation, and the creation process of wifi with different encryption methods is not very 1:


 public WifiConfiguration createWifiConfig(String SSID, @WifiCipherType int wifiCipherType, String password) {
    WifiConfiguration wifiConfiguration = new WifiConfiguration();
    wifiConfiguration.SSID = convertToQuotedString(SSID);

    switch (wifiCipherType) {
      case WifiCipherType.SECURITY_NONE:
        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        break;
      case WifiCipherType.SECURITY_WEP:
        wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
        wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
        wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
        if (!TextUtils.isEmpty(password)) {
          int length = password.length();
          // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
          if ((length == 10 || length == 26 || length == 58)
              && password.matches("[0-9A-Fa-f]*")) {
            wifiConfiguration.wepKeys[0] = password;
          } else {
            wifiConfiguration.wepKeys[0] = '"' + password + '"';
          }
        }
        break;

      case WifiCipherType.SECURITY_PSK:
        wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
        if (!TextUtils.isEmpty(password)) {
          if (password.matches("[0-9A-Fa-f]{64}")) {
            wifiConfiguration.preSharedKey = password;
          } else {
            wifiConfiguration.preSharedKey = '"' + password + '"';
          }
        }
        break;

      case WifiCipherType.SECURITY_EAP:
        wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
        wifiConfiguration.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
        wifiConfiguration.enterpriseConfig = new WifiEnterpriseConfig();
        int eapMethod = 0;
        int phase2Method = 0;
        wifiConfiguration.enterpriseConfig.setEapMethod(eapMethod);
        wifiConfiguration.enterpriseConfig.setPhase2Method(phase2Method);
        if (!TextUtils.isEmpty(password)) {
          wifiConfiguration.enterpriseConfig.setPassword(password);
        }
        break;
      default:
        break;
    }
    return wifiConfiguration;
  }

At this point, the connection of wifi is completed, and then the connection results can be obtained in the broadcast. The corresponding wifi configuration information is saved in /data/misc/wifi/wpa_supplicant. conf:


network={
    ssid="test"
    psk="88888888"
    key_mgmt=WPA-PSK
    disabled=1
    id_str="%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22test%5C%22WPA_PSK%22%7D"
}

Connect anonymous wifi

Compared with ordinary wifi, anonymous wifi is different in that it does not broadcast its SSID, so it cannot be scanned directly. We need to input SSID of wifi to actively scan. First, look at the configuration information of anonymous wifi:


network={                                                
    ssid="test2"                                          
    scan_ssid=1                                           
    bssid=56:28:f8:fa:f8:a0                                     
    psk="44444444"                                         
    key_mgmt=WPA-PSK                                        
    disabled=1                                           
    id_str="%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22test2%5C%22WPA_PSK%22%7D" 
} 

As you can see, there is one more scan_ssid attribute. Look at WifiConfiguration, and there is really one attribute that can be set


/**
   * This is a network that does not broadcast its SSID, so an
   * SSID-specific probe request must be used for scans.
   */
  public boolean hiddenSSID;

So when creating WifiConfiguration, just set this attribute more:


configuration.hiddenSSID = true

Related articles: