Руководство Android Wifi Scanning
View more Tutorials:
В Android, Wi-Fi это протокол беспроводной передачи (Wireless Network Protocol), позволяет устройствам подключиться к Internet (интернету) или подключение устройств друг к другу для обмена данных.
Точнее, Android предоставляет Wi-Fi API, приложения могут использовать данный API для управления всех аспектов связанных с подключением к Wifi, например поиск текущих сетей Wifi, добавить, сохранить, удалить сети Wifi и управлять обменявшимися данными между устройствами.

Используя Wi-Fi API в своем приложении, вы можете выполнить следующие функции:
- Сканировать (scan) для поиска готовых сетей Wifi в диапазоне.
- Позволить устройству подключиться к Internet.
- Подключить к другим устройствам через Service Discovery (Обнаружение сервисов).
- Управлять списком конфигурированных сетей.
- Управлять многими подключениями.
Начиная с Android 10.0 (API Level 29) вы не можете использовать Wi-Fi API чтобы включить/выключить (enable/disable) Wifi системы, это значит если вы хотите включить/выключить Wifi, вам нужно использовать готовые функции операционной системы.

Политика конфиденциальности для использования Wi-Fi API чтобы включить/выключить Wifi была изменена через многие версии Android. Точнее:
Android Level | Политика конфиденциальности |
Level 1 ==> Level 22 (Android < 6.0) | Нужно добавить android.permission.CHANGE_WIFI_STATE в AndroidManifest.xml. |
Level 23 ==> Level 28 (Android 6.0 - 9.x) | Нужно добавить android.permission.CHANGE_WIFI_STATE в AndroidManifest.xml, одновременно, ваше приложение должно спросить разрешение пользователя, чтобы включить/выключить Wifi системы. |
Level 29+ (Android 10.0+) | Не разрешать использовать Wi-Fi API, чтобы включить/выключить Wifi системы. |
* AndroidManifest.xml *
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(true); // Enable Wifi wifiManager.setWifiEnabled(false); // Disable Wifi
В Android 10+ (API Level 29+), метод setWifiEnabled(boolean) больше не работает.
Чтобы получить статус Wifi, вам нужно добавить android.permission.ACCESS_WIFI_STATE в AndroidManifest.xml:
* AndroidManifest.xml *
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE); int state = wifiManager.getWifiState(); String statusInfo = "Unknown"; switch (state) { case WifiManager.WIFI_STATE_DISABLING: statusInfo = "Disabling"; break; case WifiManager.WIFI_STATE_DISABLED: statusInfo = "Disabled"; break; case WifiManager.WIFI_STATE_ENABLING: statusInfo = "Enabling"; break; case WifiManager.WIFI_STATE_ENABLED: statusInfo = "Enabled"; break; case WifiManager.WIFI_STATE_UNKNOWN: statusInfo = "Unknown"; break; default: statusInfo = "Unknown"; break; }
Сканировать (scan) для поиска текущих сетей:
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE); // Get List of Available Wifi Networks List<ScanResult> availNetworks = wifiManager.getScanResults(); if (availNetworks.size() > 0) { // Get Each network detail for (int i=0; i< availNetworks.size();i++) { // ... } }
Политика конфиденциальности для сканирования (scan) текущих сетей так же была изменена через разные версии Android:
Android API Level | Политика конфиденциальности |
Level 1 ==> Level 22 (Android < 6.0) | Нужно добавить android.permission.ACCESS_COARSE_LOCATION в AndroidManifest.xml. |
Level 23+ (Android 6.0+) | Нужно добавить android.permission.ACCESS_COARSE_LOCATION в AndroidManifest.xml, одновременно ваше приложение должно спросить разрешение пользователся сканировать (scan) текущие сети. |
* AndroidManifest.xml *
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- TODO Link!
В данном примере я покажу вам как использовать WifiManager, чтобы получить статус Wifi, сканировать текущие сети, записать детальную информацию каждой найденной сети и подключить к определенной сети в списке.
Просмотр примера:


На Android Studio создать новый project:
- File > New > New Project > Empty Activity
- Name: WifiManagerExample
- Package name: org.o7planning.wifimanagerexample
- Language: Java
Добавить разрешения (permission) в приложение:
<uses-permission android:name="android.permission.ACCESS_WIFI_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_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.o7planning.wifimanagerexample"> <uses-permission android:name="android.permission.ACCESS_WIFI_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_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Пример интейфейса приложения:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/button_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:text="Show Wifi State" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button_scan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:text="Scan Wifi" app:layout_constraintStart_toEndOf="@+id/button_state" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/editText_password" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:ems="10" android:inputType="textPersonName" android:text="12345678" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button_state" /> <ScrollView android:id="@+id/scrollView" android:layout_width="0dp" android:layout_height="143dp" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:background="#F3F4EB" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editText_password"> <LinearLayout android:id="@+id/linearLayout_scanResults" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5sp" android:layout_marginTop="5sp" android:layout_marginRight="5sp" android:layout_marginBottom="5sp" android:orientation="vertical" /> </ScrollView> <TextView android:id="@+id/textView_scanResults" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:layout_marginBottom="16dp" android:background="#F1F3E7" android:inputType="textMultiLine" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/scrollView" /> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.wifimanagerexample; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String LOG_TAG = "AndroidExample"; private static final int MY_REQUEST_CODE = 123; private WifiManager wifiManager; private Button buttonState; private Button buttonScan; private EditText editTextPassword; private LinearLayout linearLayoutScanResults; private TextView textViewScanResults; private WifiBroadcastReceiver wifiReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE); // Instantiate broadcast receiver this.wifiReceiver = new WifiBroadcastReceiver(); // Register the receiver registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); // this.buttonState = (Button) this.findViewById(R.id.button_state); this.buttonScan = (Button) this.findViewById(R.id.button_scan); this.editTextPassword = (EditText) this.findViewById(R.id.editText_password); this.textViewScanResults = (TextView) this.findViewById(R.id.textView_scanResults); this.linearLayoutScanResults = (LinearLayout) this.findViewById(R.id.linearLayout_scanResults); this.buttonState.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { showWifiState(); } }); this.buttonScan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { askAndStartScanWifi(); } }); } private void askAndStartScanWifi() { // With Android Level >= 23, you have to ask the user // for permission to Call. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { // 23 int permission1 = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION); // Check for permissions if (permission1 != PackageManager.PERMISSION_GRANTED) { Log.d(LOG_TAG, "Requesting Permissions"); // Request permissions ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.ACCESS_NETWORK_STATE }, MY_REQUEST_CODE); return; } Log.d(LOG_TAG, "Permissions Already Granted"); } this.doStartScanWifi(); } private void doStartScanWifi() { this.wifiManager.startScan(); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { Log.d(LOG_TAG, "onRequestPermissionsResult"); switch (requestCode) { case MY_REQUEST_CODE: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted Log.d(LOG_TAG, "Permission Granted: " + permissions[0]); // Start Scan Wifi. this.doStartScanWifi(); } else { // Permission denied, boo! Disable the // functionality that depends on this permission. Log.d(LOG_TAG, "Permission Denied: " + permissions[0]); } break; } // Other 'case' lines to check for other // permissions this app might request. } } private void showWifiState() { int state = this.wifiManager.getWifiState(); String statusInfo = "Unknown"; switch (state) { case WifiManager.WIFI_STATE_DISABLING: statusInfo = "Disabling"; break; case WifiManager.WIFI_STATE_DISABLED: statusInfo = "Disabled"; break; case WifiManager.WIFI_STATE_ENABLING: statusInfo = "Enabling"; break; case WifiManager.WIFI_STATE_ENABLED: statusInfo = "Enabled"; break; case WifiManager.WIFI_STATE_UNKNOWN: statusInfo = "Unknown"; break; default: statusInfo = "Unknown"; break; } Toast.makeText(this, "Wifi Status: " + statusInfo, Toast.LENGTH_LONG).show(); } @Override protected void onStop() { this.unregisterReceiver(this.wifiReceiver); super.onStop(); } // Define class to listen to broadcasts class WifiBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, "onReceive()"); Toast.makeText(MainActivity.this, "Scan Complete!", Toast.LENGTH_SHORT).show(); boolean ok = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); if (ok) { Log.d(LOG_TAG, "Scan OK"); List<ScanResult> list = wifiManager.getScanResults(); MainActivity.this.showNetworks(list); MainActivity.this.showNetworksDetails(list); } else { Log.d(LOG_TAG, "Scan not OK"); } } } private void showNetworks(List<ScanResult> results) { this.linearLayoutScanResults.removeAllViews(); for( final ScanResult result: results) { final String networkCapabilities = result.capabilities; final String networkSSID = result.SSID; // Network Name. // Button button = new Button(this ); button.setText(networkSSID + " ("+networkCapabilities+")"); this.linearLayoutScanResults.addView(button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String networkCapabilities = result.capabilities; connectToNetwork(networkCapabilities, networkSSID); } }); } } private void showNetworksDetails(List<ScanResult> results) { this.textViewScanResults.setText(""); StringBuilder sb = new StringBuilder(); sb.append("Result Count: " + results.size()); for(int i = 0; i < results.size(); i++ ) { ScanResult result = results.get(i); sb.append("\n\n --------- Network " + i + "/" + results.size() + " ---------"); sb.append("\n result.capabilities: " + result.capabilities); sb.append("\n result.SSID: " + result.SSID); // Network Name. sb.append("\n result.BSSID: " + result.BSSID); sb.append("\n result.frequency: " + result.frequency); sb.append("\n result.level: " + result.level); sb.append("\n result.describeContents(): " + result.describeContents()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // Level 17, Android 4.2 sb.append("\n result.timestamp: " + result.timestamp); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Level 23, Android 6.0 sb.append("\n result.centerFreq0: " + result.centerFreq0); sb.append("\n result.centerFreq1: " + result.centerFreq1); sb.append("\n result.venueName: " + result.venueName); sb.append("\n result.operatorFriendlyName: " + result.operatorFriendlyName); sb.append("\n result.channelWidth: " + result.channelWidth); sb.append("\n result.is80211mcResponder(): " + result.is80211mcResponder()); sb.append("\n result.isPasspointNetwork(): " + result.isPasspointNetwork() ); } } this.textViewScanResults.setText(sb.toString()); } private void connectToNetwork(String networkCapabilities, String networkSSID) { Toast.makeText(this, "Connecting to network: "+ networkSSID, Toast.LENGTH_SHORT).show(); String networkPass = this.editTextPassword.getText().toString(); // WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = "\"" + networkSSID + "\""; if(networkCapabilities.toUpperCase().contains("WEP")) { // WEP Network. Toast.makeText(this, "WEP Network", Toast.LENGTH_SHORT).show(); wifiConfig.wepKeys[0] = "\"" + networkPass + "\""; wifiConfig.wepTxKeyIndex = 0; wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); } else if(networkCapabilities.toUpperCase().contains("WPA")) { // WPA Network Toast.makeText(this, "WPA Network", Toast.LENGTH_SHORT).show(); wifiConfig.preSharedKey = "\""+ networkPass +"\""; } else { // OPEN Network. Toast.makeText(this, "OPEN Network", Toast.LENGTH_SHORT).show(); wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); } this.wifiManager.addNetwork(wifiConfig); List<WifiConfiguration> list = this.wifiManager.getConfiguredNetworks(); for( WifiConfiguration config : list ) { if(config.SSID != null && config.SSID.equals("\"" + networkSSID + "\"")) { this.wifiManager.disconnect(); this. wifiManager.enableNetwork(config.networkId, true); this.wifiManager.reconnect(); break; } } } }