Wi-Fi ื•ืขื•ื“ ื”ืจื‘ื” ืงื™ืฆื•ืจื™ื. ื›ื™ืฆื“ ืœืงื‘ืœ ื ืชื•ื ื™ื ืขืœ ืฆืžืชื™ Wi-Fi ื‘ืืคืœื™ืงืฆื™ื™ืช ืื ื“ืจื•ืื™ื“ ืžื‘ืœื™ ืœื”ืชื ืคื—

ื™ื•ื ืื—ื“ ื”ื™ื™ืชื™ ืฆืจื™ืš ืœืกืจื•ืง ืจืฉืชื•ืช Wi-Fi ืžื™ื™ืฉื•ืžื™ ืื ื“ืจื•ืื™ื“ ื•ืœืงื‘ืœ ื ืชื•ื ื™ื ืžืคื•ืจื˜ื™ื ืขืœ ื ืงื•ื“ื•ืช ื’ื™ืฉื”.

ื›ืืŸ ื ืืœืฆื ื• ืœื”ืชืžื•ื“ื“ ืขื ืžืกืคืจ ืงืฉื™ื™ื: ื›ื‘ื•ื™. ืชื™ืขื•ื“ ืื ื“ืจื•ืื™ื“ ืจื‘ื™ื ืžื”ืžื—ืœืงื•ืช ื”ืžืชื•ืืจื•ืช ื”ื•ืฆืื• ืžืฉื™ืžื•ืฉ (ืจืžืช API > 26), ืžื” ืฉืœื ื‘ื ืœื™ื“ื™ ื‘ื™ื˜ื•ื™ ื‘ื”; ื”ืชื™ืื•ืจ ืฉืœ ื›ืžื” ื“ื‘ืจื™ื ื‘ืชื™ืขื•ื“ ื”ื•ื ืžื™ื ื™ืžืœื™ (ืœื“ื•ื’ืžื”, ืฉื“ื” ื”ื™ื›ื•ืœื•ืช ืฉืœ ื”ืžื—ืœืงื” ืชื•ืฆืื•ืช ืกืจื™ืงื” ื‘ื–ืžืŸ ื”ื›ืชื™ื‘ื”, ื›ืžืขื˜ ืฉื•ื ื“ื‘ืจ ืœื ืžืชื•ืืจ, ืœืžืจื•ืช ืฉื”ื•ื ืžื›ื™ืœ ื”ืจื‘ื” ื ืชื•ื ื™ื ื—ืฉื•ื‘ื™ื). ื”ืงื•ืฉื™ ื”ืฉืœื™ืฉื™ ืขืฉื•ื™ ืœื”ื™ื•ืช ื‘ืขื•ื‘ื“ื” ืฉื›ืืฉืจ ืืชื” ืžืชืงืจื‘ ืœืจืืฉื•ื ื” ืœ-Wi-Fi, ืžืœื‘ื“ ืงืจื™ืืช ื”ืชื™ืื•ืจื™ื” ื•ื”ื’ื“ืจืช ื”ื ืชื‘ ื‘ืืžืฆืขื•ืช localhost, ืืชื” ืฆืจื™ืš ืœื”ืชืžื•ื“ื“ ืขื ืžืกืคืจ ืงื™ืฆื•ืจื™ื ืฉื ืจืื™ื ืžื•ื‘ื ื™ื ื‘ื ืคืจื“. ืื‘ืœ ืื•ืœื™ ืœื ื‘ืจื•ืจ ืื™ืš ืœื”ืชื™ื™ื—ืก ื•ืœื‘ื ื•ืช ืื•ืชื (ืฉื™ืคื•ื˜ ื”ื•ื ืกื•ื‘ื™ื™ืงื˜ื™ื‘ื™ ื•ืชืœื•ื™ ื‘ื ื™ืกื™ื•ืŸ ืงื•ื“ื).

ืžืืžืจ ื–ื” ื“ืŸ ื›ื™ืฆื“ ืœื”ืฉื™ื’ ื ืชื•ื ื™ื ืžืงื™ืคื™ื ืขืœ ืกื‘ื™ื‘ืช ื”-Wi-Fi ืžืงื•ื“ ืื ื“ืจื•ืื™ื“ ืœืœื NDK, ืคืจื™ืฆื•ืช, ืืœื ืจืง ื‘ืืžืฆืขื•ืช ื”-API ืฉืœ Android ื•ืœื”ื‘ื™ืŸ ื›ื™ืฆื“ ืœืคืจืฉ ื–ืืช.

ื‘ื•ืื• ืœื ื ืชืขื›ื‘ ื•ื ืชื—ื™ืœ ืœื›ืชื•ื‘ ืงื•ื“.

1. ืฆื•ืจ ืคืจื•ื™ืงื˜

ื”ืขืจื” ื–ื• ืžื™ื•ืขื“ืช ืœืžื™ ืฉื™ืฆืจ ืคืจื•ื™ืงื˜ ืื ื“ืจื•ืื™ื“ ื™ื•ืชืจ ืžืคืขื ืื—ืช, ืœื›ืŸ ืื ื• ืžืฉืžื™ื˜ื™ื ืืช ื”ืคืจื˜ื™ื ืฉืœ ืคืจื™ื˜ ื–ื”. ื”ืงื•ื“ ืฉืœื”ืœืŸ ื™ื•ืฆื’ ื‘-Kotlin, minSdkVersion=23.

2. ื”ืจืฉืื•ืช ื’ื™ืฉื”

ื›ื“ื™ ืœืขื‘ื•ื“ ืขื Wi-Fi ืžื”ืืคืœื™ืงืฆื™ื”, ืชืฆื˜ืจืš ืœืงื‘ืœ ืžืกืคืจ ื”ืจืฉืื•ืช ืžื”ืžืฉืชืžืฉ. ื‘ื”ืชืื ืœ ืชื™ืขื•ื“, ืขืœ ืžื ืช ืœืกืจื•ืง ืืช ื”ืจืฉืช ื‘ืžื›ืฉื™ืจื™ื ืขื ื’ืจืกืื•ืช ืžืขืจื›ืช ื”ืคืขืœื” ืœืื—ืจ 8.0, ื‘ื ื•ืกืฃ ืœื’ื™ืฉื” ืœืฆืคื™ื™ื” ื‘ืžืฆื‘ ืกื‘ื™ื‘ืช ื”ืจืฉืช, ืืชื” ืฆืจื™ืš ื’ื™ืฉื” ืœืฉื™ื ื•ื™ ืžืฆื‘ ืžื•ื“ื•ืœ ื”-Wi-Fi ืฉืœ ื”ืžื›ืฉื™ืจ, ืื• ื’ื™ืฉื” ืœืงื•ืื•ืจื“ื™ื ื˜ื•ืช (ื‘ืขืจืš ืื• ืžื“ื•ื™ืง). ื”ื—ืœ ืžื’ืจืกื” 9.0, ืขืœื™ืš ืœื‘ืงืฉ ืžื”ืžืฉืชืžืฉ ืืช ืฉื ื™ื”ื, ื•ื’ื ืœื‘ืงืฉ ืžื”ืžืฉืชืžืฉ ื‘ืื•ืคืŸ ืžืคื•ืจืฉ ืœื”ืคืขื™ืœ ืฉื™ืจื•ืชื™ ืžื™ืงื•ื. ืืœ ืชืฉื›ื—ื• ืœื”ืกื‘ื™ืจ ืœืžืฉืชืžืฉ ื‘ื’ื‘ื•ืจื” ืฉื–ื• ื”ื’ื—ืžื” ืฉืœ ื’ื•ื’ืœ, ื•ืœื ื”ืจืฆื•ืŸ ืฉืœื ื• ืœืจื’ืœ ืื—ืจื™ื• :)

ืื– ื‘-AndroidManifest.xml ื ื•ืกื™ืฃ:

    <uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
    <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_FINE_LOCATION"/>

ื•ื‘ืงื•ื“ ืฉืžื›ื™ืœ ืงื™ืฉื•ืจ ืœืคืขื™ืœื•ืช ื”ื ื•ื›ื—ื™ืช:

import android.app.Activity
import android.content.Context
import android.location.LocationManager
import androidx.core.app.ActivityCompat

....

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
            makeEnableLocationServices(activity.applicationContext)
        } else {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
        }

    /* ะฒะบะปัŽั‡ะฐะตั‚ ัะบั€ะฐะฝ ะฒะบะปัŽั‡ะตะฝะธั ัะปัƒะถะฑั‹ ะฟะพ ะพะฟั€ะตะดะตะปะตะฝะธัŽ ะผะตัั‚ะพะฟะพะปะพะถะตะฝะธั */
    fun makeEnableLocationServices(context: Context) {
        // TODO: ะฟะตั€ะตะด ะฒั‹ะทะพะฒะพะผ ัั‚ะพะน ั„ัƒะฝะบั†ะธะธ ะฝะฐะดะพ ั€ะฐััะบะฐะทะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŽ, ะทะฐั‡ะตะผ ะ’ะฐะผ ะดะพัั‚ัƒะฟ ะบ ะผะตัั‚ะพะฟะพะปะพะถะตะฝะธัŽ
        val lm: LocationManager =
            context.applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

        val gpsEnabled: Boolean = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        val networkEnabled: Boolean = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!gpsEnabled && !networkEnabled) {
            context.startActivity(Intent(ACTION_LOCATION_SOURCE_SETTINGS));
        }
    }

3. ืฆื•ืจ BroadcastReceiver ื•ื”ื™ืจืฉื ืœืื™ืจื•ืขื™ ืขื“ื›ื•ืŸ ื ืชื•ื ื™ื ืขืœ ืกืจื™ืงืช ืกื‘ื™ื‘ืช ืจืฉืช ื”-Wi-Fi

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } 
  }
}

val intentFilter = IntentFilter()
/* ะฟะพะดะฟะธัั‹ะฒะฐะตะผัั ะฝะฐ ัะพะพะฑั‰ะตะฝะธั ะพ ะฟะพะปัƒั‡ะตะฝะธะธ ะฝะพะฒั‹ั… ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะฒ ัะบะฐะฝะธั€ะพะฒะฐะฝะธั */
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  /* ั‡ั‚ะพ-ั‚ะพ ะฝะต ะฟะพะปัƒั‡ะธะปะพััŒ ะฟั€ะธ ะทะฐะฟัƒัะบะต ัะบะฐะฝะธั€ะพะฒะฐะฝะธั, ะฟั€ะพะฒะตั€ัŒั‚ะต ะฒั‹ะดะฐะฝั‹ะต ั€ะฐะทั€ะตัˆะตะฝะธั */
}

....

private fun scanSuccess() {
 /* ะฒะพั‚ ะพะฝะธ, ั€ะตะทัƒะปัŒั‚ะฐั‚ั‹ ัะบะฐะฝะธั€ะพะฒะฐะฝะธั */
  val results: List<ScanResult> = wifiManager.scanResults
}

ืฉื™ื˜ืช WiFiManager.startScan ื‘ืชื™ืขื•ื“ ืžืกื•ืžื ืช ื›ืžืชื•ื—ืœืช ืžืื– ื’ื™ืจืกืช API 28, ืืš ื›ื‘ื•ื™ื”. ืžื“ืจื™ืš ืžืฆื™ืข ืœื”ืฉืชืžืฉ ื‘ื•.

ื‘ืกืš ื”ื›ืœ ืงื™ื‘ืœื ื• ืจืฉื™ืžื” ืฉืœ ื—ืคืฆื™ื ืชื•ืฆืื•ืช ืกืจื™ืงื”.

4. ืขื™ื™ืŸ ื‘-ScanResult ื•ื”ื‘ื™ืŸ ืืช ื”ืชื ืื™ื

ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื›ืžื” ืฉื“ื•ืช ื‘ื›ื™ืชื” ื–ื• ื•ื ืชืืจ ืืช ืžืฉืžืขื•ืชื:

SSID โ€” ืžื–ื”ื” ืขืจื›ืช ืฉื™ืจื•ืช ื”ื•ื ืฉื ื”ืจืฉืช

BSSID - ืžื–ื”ื” ืขืจื›ืช ืฉื™ืจื•ืช ื‘ืกื™ืกื™ืช - ื›ืชื•ื‘ืช MAC ืฉืœ ืžืชืื ื”ืจืฉืช (ื ืงื•ื“ืช Wi-Fi)

ืจึธืžึธื” โ€” ืžื—ื•ื•ืŸ ืขื•ืฆืžืช ืื•ืช ืžืชืงื‘ืœ [dBm (dBm ืจื•ืกื™ืช) โ€” ื“ืฆื™ื‘ืœ, ื”ืกืคืง ื™ื™ื—ื•ืก 1 mW.] โ€” ืื™ื ื“ื™ืงื˜ื•ืจ ืฉืœ ืขื•ืฆืžืช ื”ืื•ืช ื”ืžืชืงื‘ืœ. ืœื•ืงื— ืขืจืš ืž-0 ืขื“ -100, ื›ื›ืœ ืฉื”ืจื—ืง ืž-0, ื›ืš ืื‘ื“ ื™ื•ืชืจ ื›ื•ื— ื”ืื•ืช ืœืื•ืจืš ื”ื“ืจืš ืžื ืงื•ื“ืช ื”-Wi-Fi ืœืžื›ืฉื™ืจ ืฉืœืš. ืคืจื˜ื™ื ื ื•ืกืคื™ื ื ื™ืชืŸ ืœืžืฆื•ื, ืœืžืฉืœ, ื‘ื›ืชื•ื‘ืช ื•ื™ืงื™ืคื“ื™ื”. ื›ืืŸ ืื ื™ ืื’ื™ื“ ืœืš ืฉืฉื™ืžื•ืฉ ื‘ื›ื™ืชื” ืื ื“ืจื•ืื™ื“ WifiManager ืืชื” ื™ื›ื•ืœ ืœื›ื™ื™ืœ ืืช ืจืžืช ื”ืื•ืช ื‘ืงื ื” ืžื™ื“ื” ืžืžืฆื•ื™ืŸ ืขื“ ื ื•ืจื ื‘ืฉืœื‘ ืฉืืชื” ื‘ื•ื—ืจ:

        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val numberOfLevels = 5
        val level = WifiManager.calculateSignalLevel(level, numberOfLevels)

ืชื“ืจ - ืชื“ืจ ื”ื”ืคืขืœื” ืฉืœ ื ืงื•ื“ืช ื”-Wi-Fi [Hz]. ื‘ื ื•ืกืฃ ืœืชื“ืจ ืขืฆืžื•, ื™ื™ืชื›ืŸ ืฉืชืชืขื ื™ื™ืŸ ื‘ืžื” ืฉื ืงืจื ืขืจื•ืฅ. ืœื›ืœ ื ืงื•ื“ื” ื™ืฉ โ€‹โ€‹ื˜ื•ื”ืจ ื”ืคืขืœื” ืžืฉืœื”. ื‘ื–ืžืŸ ื”ื›ืชื™ื‘ื”, ื”ื˜ื•ื•ื— ื”ืคื•ืคื•ืœืจื™ ื‘ื™ื•ืชืจ ืฉืœ ื ืงื•ื“ื•ืช Wi-Fi ื”ื•ื 2.4 ื’ื™ื’ื”-ื”ืจืฅ. ืื‘ืœ, ืœื™ืชืจ ื“ื™ื•ืง, ื”ื ืงื•ื“ื” ืžืฉื“ืจืช ืžื™ื“ืข ืœื˜ืœืคื•ืŸ ืฉืœืš ื‘ืชื“ืจ ืžืžื•ืกืคืจ ืงืจื•ื‘ ืœื–ื” ืฉืฉืžื•. ืžืกืคืจ ืขืจื•ืฆื™ื ื•ืชื“ืจื™ื ืžืชืื™ืžื™ื ืžึฐืชื•ึผืงื ึธืŸ. ื–ื” ื ืขืฉื” ื›ื“ื™ ืฉื ืงื•ื“ื•ืช ืกืžื•ื›ื•ืช ื™ืคืขืœื• ื‘ืชื“ืจื™ื ืฉื•ื ื™ื, ื•ื‘ื›ืš ืœื ืžืคืจื™ืขื•ืช ื–ื• ืœื–ื• ื•ืœื ืžืคื—ื™ืชื•ืช ื”ื“ื“ื™ืช ืืช ืžื”ื™ืจื•ืช ื•ืื™ื›ื•ืช ื”ืฉื™ื“ื•ืจ. ื‘ืžืงืจื” ื–ื”, ื”ื ืงื•ื“ื•ืช ืคื•ืขืœื•ืช ืœื ื‘ืชื“ืจ ืื—ื“, ืืœื ื‘ื˜ื•ื•ื— ืฉืœ ืชื“ืจื™ื (ืคืจืžื˜ืจ ืจื•ื—ื‘ ืขืจื•ืฅ), ื ืงืจื ืจื•ื—ื‘ ื”ืขืจื•ืฅ. ื›ืœื•ืžืจ, ื ืงื•ื“ื•ืช ื”ืคื•ืขืœื•ืช ื‘ืขืจื•ืฆื™ื ืกืžื•ื›ื™ื (ื•ืœื ืจืง ืกืžื•ื›ื™ื, ืืœื ืืคื™ืœื• 3 ืžืขืฆืžื) ืžืคืจื™ืขื•ืช ื–ื• ืœื–ื•. ื™ื™ืชื›ืŸ ืฉืชืžืฆื ืืช ื”ืงื•ื“ ื”ืคืฉื•ื˜ ื”ื–ื” ืฉื™ืžื•ืฉื™, ื”ืžืืคืฉืจ ืœืš ืœื—ืฉื‘ ืืช ืžืกืคืจ ื”ืขืจื•ืฅ ืžืขืจืš ื”ืชื“ืจ ืขื‘ื•ืจ ื ืงื•ื“ื•ืช ืขื ืชื“ืจ ืฉืœ 2.4 ื•-5 Ghz:


    /* ะฟะพ ั‡ะฐัั‚ะพั‚ะต ะพะฟั€ะตะดะตะปัะตะผ ะฝะพะผะตั€ ะบะฐะฝะฐะปะฐ */
    val channel: Int
        get() {
            return if (frequency in 2412..2484) {
                (frequency - 2412) / 5 + 1
            } else if (frequency in 5170..5825) {
                (frequency - 5170) / 5 + 34
            } else {
                -1
            }
        }

ื™ื›ื•ืœื•ืช - ื”ืชื—ื•ื ื”ืžืขื ื™ื™ืŸ ื‘ื™ื•ืชืจ ืœื ื™ืชื•ื—, ื”ืขื‘ื•ื“ื” ืื™ืชื• ื“ืจืฉื” ื”ืจื‘ื” ื–ืžืŸ. ื›ืืŸ ื›ืชื•ื‘ื•ืช "ื”ื™ื›ื•ืœื•ืช" ืฉืœ ื”ื ืงื•ื“ื” ื‘ืฉื•ืจื”. ื‘ืžืงืจื” ื–ื”, ืื™ื ืš ืฆืจื™ืš ืœื—ืคืฉ ืคืจื˜ื™ื ืขืœ ืคืจืฉื ื•ืช ืžื—ืจื•ื–ืช ื‘ืชื™ืขื•ื“. ื”ื ื” ื›ืžื” ื“ื•ื’ืžืื•ืช ืœืžื” ืฉืขืฉื•ื™ ืœื”ื™ื•ืช ื‘ืฉื•ืจื” ื”ื–ื•:

[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][WPS][ESS]
[WPA2-PSK-CCMP][ESS]
[WPA2-PSK-CCMP+TKIP][ESS]
[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS]
[ESS][WPS]

5. ื”ื‘ื ืช ืงื™ืฆื•ืจื™ื ื•ื™ื›ื•ืœื•ืช ื ื™ืชื•ื—

ืจืื•ื™ ืœื”ื–ื›ื™ืจ ืฉื”ืžื—ืœืงื•ืช ืฉืœ ื—ื‘ื™ืœืช android.net.wifi.* ืžืฉืžืฉื•ืช ืžืชื—ืช ืœืžื›ืกื” ื”ืžื ื•ืข ืขืœ ื™ื“ื™ ื›ืœื™ ืขื–ืจ ืœื™ื ื•ืงืก wpa_supplicant ื•ืชื•ืฆืืช ื”ืคืœื˜ ื‘ืฉื“ื” ื”ื™ื›ื•ืœื•ืช ื”ื™ื ืขื•ืชืง ืฉืœ ืฉื“ื” ื”ื“ื’ืœื™ื ื‘ืขืช ืกืจื™ืงื”.

ื ืคืขืœ ื‘ืขืงื‘ื™ื•ืช. ื‘ื•ืื• ื ื‘ื—ืŸ ืชื—ื™ืœื” ืืช ื”ืคืœื˜ ืฉืœ ืคื•ืจืžื˜ ืฉื‘ื• ืืœืžื ื˜ื™ื ื‘ืชื•ืš ืกื•ื’ืจื™ื™ื ืžื•ืคืจื“ื™ื ื‘ืกื™ืžืŸ "-":

[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]

ื”ืžืฉืžืขื•ืช ื”ืจืืฉื•ื ื” ืžืชืืจืช โ€‹โ€‹ืืช ืžื” ืฉื ืงืจื. ืฉื™ื˜ืช ืื™ืžื•ืช. ื›ืœื•ืžืจ, ืื™ื–ื” ืจืฆืฃ ืฉืœ ืคืขื•ืœื•ืช ืขืœ ื”ืžื›ืฉื™ืจ ื•ื ืงื•ื“ืช ื”ื’ื™ืฉื” ืœื‘ืฆืข ื›ื“ื™ ืฉื ืงื•ื“ืช ื”ื’ื™ืฉื” ืชืืคืฉืจ ืฉื™ืžื•ืฉ ื‘ืขืฆืžื” ื•ื›ื™ืฆื“ ืœื”ืฆืคื™ืŸ ืืช ื”ืžื˜ืขืŸ. ื‘ื–ืžืŸ ื›ืชื™ื‘ืช ืคื•ืกื˜ ื–ื”, ื”ืืคืฉืจื•ื™ื•ืช ื”ื ืคื•ืฆื•ืช ื‘ื™ื•ืชืจ ื”ืŸ WPA ื•-WPA2, ืฉื‘ื”ืŸ ื›ืœ ืžื›ืฉื™ืจ ืžื—ื•ื‘ืจ ื™ืฉื™ืจื•ืช ืื• ื“ืจืš ืžื” ืฉื ืงืจื. ืฉืจืช RADIUS (WPA-Enterprice) ืžืกืคืง ืืช ื”ืกื™ืกืžื” ื‘ืขืจื•ืฅ ืžื•ืฆืคืŸ. ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉื ืงื•ื“ืช ื”ื’ื™ืฉื” ื‘ื‘ื™ืชืš ืžืกืคืงืช ื—ื™ื‘ื•ืจ ื‘ื”ืชืื ืœืชื›ื ื™ืช ื–ื•. ื”ื”ื‘ื“ืœ ื‘ื™ืŸ ื”ื’ืจืกื” ื”ืฉื ื™ื™ื” ืœื’ืจืกื” ื”ืจืืฉื•ื ื” ื”ื•ื ืฉื™ืฉ ืœื” ืฆื•ืคืŸ ื—ื–ืง ื™ื•ืชืจ: AES ืœืขื•ืžืช TKIP ื”ืœื ืžืื•ื‘ื˜ื—. ื’ื WPA3, ืฉื”ื•ื ืžื•ืจื›ื‘ ื•ืžืชืงื“ื ื™ื•ืชืจ, ืžื•ืฆื’ ื‘ื”ื“ืจื’ื”. ืชื™ืื•ืจื˜ื™ืช, ื™ื™ืชื›ืŸ ืฉื™ืฉ ืืคืฉืจื•ืช ืขื ืคืชืจื•ืŸ ื”-Enterprice CCKM (Cisco Centralized Key Management), ืื‘ืœ ืžืขื•ืœื ืœื ื ืชืงืœืชื™ ื‘ื”.

ื™ื™ืชื›ืŸ ืฉื ืงื•ื“ืช ื”ื’ื™ืฉื” ื”ื•ื’ื“ืจื” ืœืื™ืžื•ืช ืœืคื™ ื›ืชื•ื‘ืช MAC. ืœื—ืœื•ืคื™ืŸ, ืื ื ืงื•ื“ืช ื”ื’ื™ืฉื” ืžืกืคืงืช ื ืชื•ื ื™ื ื‘ืืžืฆืขื•ืช ืืœื’ื•ืจื™ืชื WEP ื”ืžื™ื•ืฉืŸ, ืœืžืขืฉื” ืื™ืŸ ืื™ืžื•ืช (ื”ืžืคืชื— ื”ืกื•ื“ื™ ื›ืืŸ ื”ื•ื ืžืคืชื— ื”ื”ืฆืคื ื”). ืื ื• ืžืกื•ื•ื’ื™ื ืืคืฉืจื•ื™ื•ืช ื›ืืœื” ื›ืฉืืจ.
ื™ืฉื ื” ื’ื ืฉื™ื˜ื” ืคื•ืคื•ืœืจื™ืช ื‘-wi-fi ืฆื™ื‘ื•ืจื™ ืขื Captive Portal Detection ืžื•ืกืชืจ - ื‘ืงืฉืช ืื™ืžื•ืช ื“ืจืš ื“ืคื“ืคืŸ. ื ืงื•ื“ื•ืช ื’ื™ืฉื” ื›ืืœื” ื ืจืื•ืช ืœืกื•ืจืง ื›ืคืชื•ื—ื•ืช (ืฉื”ืŸ ืžื ืงื•ื“ืช ื”ืžื‘ื˜ ืฉืœ ื”ื—ื™ื‘ื•ืจ ื”ืคื™ื–ื™). ืœื›ืŸ, ืื ื• ืžืกื•ื•ื’ื™ื ืื•ืชื ื›-OPEN.

ื”ืขืจืš ื”ืฉื ื™ ื™ื›ื•ืœ ืœื”ื™ื•ืช ืžืกื•ืžืŸ ื› ืืœื’ื•ืจื™ืชื ื ื™ื”ื•ืœ ืžืคืชื—. ื–ื”ื• ืคืจืžื˜ืจ ืฉืœ ืฉื™ื˜ืช ื”ืื™ืžื•ืช ืฉืชื•ืืจื” ืœืขื™ืœ. ืžื“ื‘ืจ ืขืœ ืื™ืš ื‘ื“ื™ื•ืง ืžื—ืœื™ืคื™ื ืžืคืชื—ื•ืช ื”ืฆืคื ื”. ื‘ื•ืื• ื ื‘ื—ืŸ ืืช ื”ืืคืฉืจื•ื™ื•ืช ื”ืืคืฉืจื™ื•ืช. EAP - ื‘ืฉื™ืžื•ืฉ ื‘-WPA-Enterprice ืฉื”ื•ื–ื›ืจ, ืžืฉืชืžืฉ ื‘ืžืกื“ ื ืชื•ื ื™ื ื›ื“ื™ ืœืืžืช ืืช ื ืชื•ื ื™ ื”ืื™ืžื•ืช ืฉื”ื•ื–ื ื•. SAE - ืžืฉืžืฉ ื‘-WPA3 ืžืชืงื“ื, ืขืžื™ื“ ื™ื•ืชืจ ื‘ืคื ื™ ื›ื•ื— ื’ืก. PSK - ื”ืืคืฉืจื•ืช ื”ื ืคื•ืฆื” ื‘ื™ื•ืชืจ, ื›ื•ืœืœืช ื”ื–ื ืช ืกื™ืกืžื” ื•ื”ืขื‘ืจืชื” ื‘ืฆื•ืจื” ืžื•ืฆืคื ืช. IEEE8021X - ืœืคื™ ืชืงืŸ ื‘ื™ื ืœืื•ืžื™ (ืฉื•ื ื” ืžื–ื” ืฉื ืชืžืš ืขืœ ื™ื“ื™ ืžืฉืคื—ืช WPA). OWE (Opportunistic Wireless Encryption) ื”ื™ื ื”ืจื—ื‘ื” ืฉืœ ืชืงืŸ IEEE 802.11 ืขื‘ื•ืจ ื ืงื•ื“ื•ืช ืฉืกื™ื•ื•ื’ื ื• ื›-OPEN. OWE ืžื‘ื˜ื™ื— ืืช ืื‘ื˜ื—ืช ื”ื ืชื•ื ื™ื ื”ืžื•ืขื‘ืจื™ื ื‘ืจืฉืช ืœื ืžืื•ื‘ื˜ื—ืช ืขืœ ื™ื“ื™ ื”ืฆืคื ืชื. ืืคืฉืจื•ืช ืืคืฉืจื™ืช ื’ื ื›ืฉืื™ืŸ ืžืคืชื—ื•ืช ื’ื™ืฉื”, ื ืงืจื ืœืืคืฉืจื•ืช ื”ื–ื• NONE.

ื”ืคืจืžื˜ืจ ื”ืฉืœื™ืฉื™ ื”ื•ื ืžื” ืฉื ืงืจื. ืชื•ื›ื ื™ื•ืช ื”ืฆืคื ื” - ื›ื™ืฆื“ ื‘ื“ื™ื•ืง ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืฆื•ืคืŸ ื›ื“ื™ ืœื”ื’ืŸ ืขืœ ื”ื ืชื•ื ื™ื ื”ืžื•ืขื‘ืจื™ื. ื‘ื•ืื• ื ืจืฉื•ื ืืช ื”ืืคืฉืจื•ื™ื•ืช. WEP - ืžืฉืชืžืฉ ื‘ืฆื•ืคืŸ ื–ืจื RC4, ื”ืžืคืชื— ื”ืกื•ื“ื™ ื”ื•ื ืžืคืชื— ื”ื”ืฆืคื ื”, ืžื” ืฉื ื—ืฉื‘ ืœื ืžืงื•ื‘ืœ ื‘ืขื•ืœื ื”ื”ืฆืคื ื” ื”ืžื•ื“ืจื ื™. TKIP - ื‘ืฉื™ืžื•ืฉ ื‘-WPA, CKIP - ื‘-WPA2. TKIP+CKIP - ื ื™ืชืŸ ืœืฆื™ื™ืŸ ื‘ื ืงื•ื“ื•ืช ื”ืžืกื•ื’ืœื•ืช ืœ-WPA ื•-WPA2 ืœื”ืชืืžื” ืœืื—ื•ืจ.

ื‘ืžืงื•ื ืฉืœื•ืฉื” ืืœืžื ื˜ื™ื, ืืชื” ื™ื›ื•ืœ ืœืžืฆื•ื ืกื™ืžืŸ WEP ื‘ื•ื“ื“:

[WEP]

ื›ืคื™ ืฉื“ื™ื‘ืจื ื• ืœืžืขืœื”, ื–ื” ืžืกืคื™ืง ื›ื“ื™ ืœื ืœืฆื™ื™ืŸ ืืช ื”ืืœื’ื•ืจื™ืชื ืœืฉื™ืžื•ืฉ ื‘ืžืคืชื—ื•ืช, ืฉืื™ื ื• ืงื™ื™ื, ื•ืืช ืฉื™ื˜ืช ื”ื”ืฆืคื ื”, ืฉื”ื™ื ื–ื”ื” ื›ื‘ืจื™ืจืช ืžื—ื“ืœ.

ืขื›ืฉื™ื• ืฉืงื•ืœ ืืช ื”ืกื•ื’ืจ ื”ื–ื”:

[ESS]

ื–ื” ืžืฆื‘ ื”ืคืขืœื” ืฉืœ Wi-Fi ืื• ื˜ื•ืคื•ืœื•ื’ื™ื” ืฉืœ ืจืฉืช Wi-Fi. ืืชื” ืขืœื•ืœ ืœื”ื™ืชืงืœ ื‘ืžืฆื‘ BSS (Basic Service Set) - ื›ืืฉืจ ื™ืฉ ื ืงื•ื“ืช ื’ื™ืฉื” ืื—ืช ืฉื“ืจื›ื” ืžื›ืฉื™ืจื™ื ืžื—ื•ื‘ืจื™ื ืžืชืงืฉืจื™ื. ื ื™ืชืŸ ืœืžืฆื•ื ื‘ืจืฉืชื•ืช ืžืงื•ืžื™ื•ืช. ื›ื›ืœืœ, ื™ืฉ ืฆื•ืจืš ื‘ื ืงื•ื“ื•ืช ื’ื™ืฉื” ืœื—ื™ื‘ื•ืจ ื”ืชืงื ื™ื ืžืจืฉืชื•ืช ืžืงื•ืžื™ื•ืช ืฉื•ื ื•ืช, ื›ืš ืฉื”ืŸ ื—ืœืง ืž-Extended Service Sets - ESS. ืกื•ื’ ื”-IBSSs (Independent Basic Service Sets) ืžืฆื™ื™ืŸ ืฉื”ืžื›ืฉื™ืจ ื”ื•ื ื—ืœืง ืžืจืฉืช Peer-to-Peer.

ื™ื™ืชื›ืŸ ืฉืชืจืื” ื’ื ืืช ื“ื’ืœ ื”-WPS:

[WPS]

WPS (ื”ื’ื“ืจื” ืžื•ื’ื ืช Wi-Fi) ื”ื•ื ืคืจื•ื˜ื•ืงื•ืœ ืœืืชื—ื•ืœ ื—ืฆื™ ืื•ื˜ื•ืžื˜ื™ ืฉืœ ืจืฉืช Wi-Fi. ื›ื“ื™ ืœืืชื—ืœ, ื”ืžืฉืชืžืฉ ืžื–ื™ืŸ ืกื™ืกืžื” ื‘ืช 8 ืชื•ื•ื™ื ืื• ืœื•ื—ืฅ ืขืœ ื›ืคืชื•ืจ ื‘ื ืชื‘. ืื ื ืงื•ื“ืช ื”ื’ื™ืฉื” ืฉืœืš ื”ื™ื ืžื”ืกื•ื’ ื”ืจืืฉื•ืŸ ื•ืชื™ื‘ืช ืกื™ืžื•ืŸ ื–ื• ืžื•ืคื™ืขื” ืœืฆื“ ืฉื ื ืงื•ื“ืช ื”ื’ื™ืฉื” ืฉืœืš, ืžื•ืžืœืฅ ืžืื•ื“ ืœืขื‘ื•ืจ ืœืœื•ื— ื”ื ื™ื”ื•ืœ ื•ืœื”ืฉื‘ื™ืช ืืช ื’ื™ืฉืช WPS. ื”ืขื•ื‘ื“ื” ื”ื™ื ืฉืœืขืชื™ื ืงืจื•ื‘ื•ืช ื ื™ืชืŸ ืœื’ืœื•ืช ืืช ื”-PIN ื‘ืŸ 8 ื”ืกืคืจื•ืช ืขืœ ื™ื“ื™ ื›ืชื•ื‘ืช ื”-MAC, ืื• ืฉื ื™ืชืŸ ืœืžื™ื™ืŸ ืื•ืชื• ื‘ื–ืžืŸ ืฆืคื•ื™, ืฉืžื™ืฉื”ื• ื™ื›ื•ืœ ืœื ืฆืœ ื‘ืื•ืคืŸ ืœื ื™ืฉืจ.

6. ืฆื•ืจ ืžื•ื“ืœ ื•ืคื•ื ืงืฆื™ื™ืช ื ื™ืชื•ื—

ื‘ื”ืชื‘ืกืก ืขืœ ืžื” ืฉื’ื™ืœื™ื ื• ืœืขื™ืœ, ื ืชืืจ ืžื” ืงืจื” ื‘ืืžืฆืขื•ืช ืžื—ืœืงื•ืช ื ืชื•ื ื™ื:

/* ัั…ะตะผะฐ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ */
enum class AuthMethod {
    WPA3,
    WPA2,
    WPA, // Wi-Fi Protected Access
    OTHER, // ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั Shared Key Authentication ะธ ะดั€. ะธัะฟะพะปัŒะทัƒัŽั‰ะธะต mac-address-based ะธ WEP
    CCKM, // Cisco
    OPEN // Open Authentication. ะœะพะถะตั‚ ะฑั‹ั‚ัŒ ัะพ ัะบั€ั‹ั‚ั‹ะผ Captive Portal Detection - ะทะฐะฟั€ะพั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ั‡ะตั€ะตะท ะฑั€ะฐัƒะทะตั€
}

/* ะฐะปะณะพั€ะธั‚ะผ ะฒะฒะพะดะฐ ะบะปัŽั‡ะตะน */
enum class KeyManagementAlgorithm {
    IEEE8021X, // ะฟะพ ัั‚ะฐะฝะดะฐั€ั‚ัƒ
    EAP, // Extensible Authentication Protocol, ั€ะฐััˆะธั€ัะตะผั‹ะน ะฟั€ะพั‚ะพะบะพะป ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ
    PSK, // Pre-Shared Key โ€” ะบะฐะถะดั‹ะน ัƒะทะตะป ะฒะฒะพะดะธั‚ ะฟะฐั€ะพะปัŒ ะดะปั ะดะพัั‚ัƒะฟะฐ ะบ ัะตั‚ะธ
    WEP, // ะฒ WEP ะฟะฐั€ะพะปัŒ ัะฒะปัะตั‚ัั ะบะปัŽั‡ะพะผ ัˆะธั„ั€ะพะฒะฐะฝะธั (No auth key)
    SAE, // Simultaneous Authentication of Equals - ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฒ WPA3
    OWE, // Opportunistic Wireless Encryption - ะฒ ั€ะพัƒั‚ะตั€ะฐั… ะฝะพะฒั‹ั… ะฟะพะบะพะปะตะฝะธะน, ะฟัƒะฑะปะธั‡ะฝั‹ั… ัะตั‚ัั… ั‚ะธะฟะฐ OPEN
    NONE // ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑะตะท ัˆะธั„ั€ะพะฒะฐะฝะธั ะฒ OPEN, OTHER
}

/* ะผะตั‚ะพะด ัˆะธั„ั€ะพะฒะฐะฝะธั */
enum class CipherMethod {
    WEP, // Wired Equivalent Privacy, ะะฝะฐะปะพะณ ัˆะธั„ั€ะพะฒะฐะฝะธั ั‚ั€ะฐั„ะธะบะฐ ะฒ ะฟั€ะพะฒะพะดะฝั‹ั… ัะตั‚ัั…
    TKIP, // Temporal Key Integrity Protocol
    CCMP, // Counter Mode with Cipher Block Chaining Message Authentication Code Protocol,
    // ะฟั€ะพั‚ะพะบะพะป ะฑะปะพั‡ะฝะพะณะพ ัˆะธั„ั€ะพะฒะฐะฝะธั ั ะบะพะดะพะผ ะฐัƒั‚ะตะฝั‚ะธั‡ะฝะพัั‚ะธ ัะพะพะฑั‰ะตะฝะธั ะธ ั€ะตะถะธะผะพะผ ัั†ะตะฟะปะตะฝะธั ะฑะปะพะบะพะฒ ะธ ัั‡ะตั‚ั‡ะธะบะฐ
    // ะฝะฐ ะพัะฝะพะฒะต AES
    NONE // ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑะตะท ัˆะธั„ั€ะพะฒะฐะฝะธั ะฒ OPEN, OTHER
}

/* ะฝะฐะฑะพั€ ะผะตั‚ะพะดะพะฒ ัˆะธั„ั€ะพะฒะฐะฝะธั ะธ ะฟั€ะพั‚ะพะบะพะปะพะฒ, ะฟะพ ะบะพั‚ะพั€ั‹ะผ ะผะพะถะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะพั‡ะบะฐ */
data class Capability(
    var authScheme: AuthMethod? = null,
    var keyManagementAlgorithm: KeyManagementAlgorithm? = null,
    var cipherMethod: CipherMethod? = null
)

/* ะ ะตะถะธะผ ั€ะฐะฑะพั‚ั‹ WiFi (ะธะปะธ ั‚ะพะฟะพะปะพะณะธั ัะตั‚ะตะน WiFi) */
enum class TopologyMode {
    IBSS, // ะญะฟะธะทะพะดะธั‡ะตัะบะฐั ัะตั‚ัŒ (Ad-Hoc ะธะปะธ IBSS โ€“ Independent Basic Service Set).
    BSS, // ะžัะฝะพะฒะฝะฐั ะทะพะฝะฐ ะพะฑัะปัƒะถะธะฒะฐะฝะธั Basic Service Set (BSS) ะธะปะธ Infrastructure Mode.
    ESS // ะ ะฐััˆะธั€ะตะฝะฝะฐั ะทะพะฝะฐ ะพะฑัะปัƒะถะธะฒะฐะฝะธั ESS โ€“ Extended Service Set.
}

ื›ืขืช ื ื›ืชื•ื‘ ืคื•ื ืงืฆื™ื” ืฉืชื ืชื— ืืช ืฉื“ื” ื”ื™ื›ื•ืœื•ืช:


private fun parseCapabilities(capabilitiesString: String): List < Capability > {
    val capabilities: List < Capability > = capabilitiesString
        .splitByBrackets()
        .filter {
            !it.isTopology() && !it.isWps()
        }
        .flatMap {
            parseCapability(it)
        }
    return
        if (!capabilities.isEmpty()) {
            capabilities
        } else {
            listOf(Capability(AuthMethod.OPEN, KeyManagementAlgorithm.NONE, CipherMethod.NONE))
        }
}

private fun parseCapability(part: String): List < Capability > {
    if (part.contains("WEP")) {
        return listOf(Capability(
            AuthMethod.OTHER,
            KeyManagementAlgorithm.WEP,
            CipherMethod.WEP
        ))
    }

    val authScheme = when {
        part.contains("WPA3") - > AuthMethod.WPA3
        part.contains("WPA2") - > AuthMethod.WPA2
        part.contains("WPA") - > AuthMethod.WPA
        else - > null
    }

    val keyManagementAlgorithm = when {
        part.contains("OWE") - > KeyManagementAlgorithm.OWE
        part.contains("SAE") - > KeyManagementAlgorithm.SAE
        part.contains("IEEE802.1X") - > KeyManagementAlgorithm.IEEE8021X
        part.contains("EAP") - > KeyManagementAlgorithm.EAP
        part.contains("PSK") - > KeyManagementAlgorithm.PSK
        else - > null
    }

    val capabilities = ArrayList < Capability > ()
    if (part.contains("TKIP") || part.contains("CCMP")) {
        if (part.contains("TKIP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.TKIP
            ))
        }
        if (part.contains("CCMP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.CCMP
            ))
        }
    } else if (authScheme != null || keyManagementAlgorithm != null) {
        capabilities.add(Capability(
            authScheme ? : AuthMethod.OPEN,
            keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
            CipherMethod.NONE
        ))
    }

    return capabilities
}

private fun parseTopologyMode(capabilitiesString: String): TopologyMode ? {
    return capabilitiesString
        .splitByBrackets()
        .mapNotNull {
            when {
                it.contains("ESS") - > TopologyMode.ESS
                it.contains("BSS") - > TopologyMode.BSS
                it.contains("IBSS") - > TopologyMode.IBSS
                else - > null
            }
        }
        .firstOrNull()
}

private fun parseWPSAvailable(capabilitiesString: String): Boolean {
    return capabilitiesString
        .splitByBrackets()
        .any {
            it.isWps()
        }
}

private fun String.splitByBrackets(): List < String > {
    val m = Pattern.compile("[(.*?)]").matcher(this)
    val parts = ArrayList < String > ()
    while (m.find()) {
        parts.add(m.group().replace("[", "").replace("]", ""))
    }
    return parts
}

private fun String.isTopology(): Boolean {
    return TopologyMode.values().any {
        this == it.name
    }
}

private fun String.isWps(): Boolean {
    return this == "WPS"
}

8. ืจืื” ืืช ื”ืชื•ืฆืื”

ืื ื™ ืืกืจื•ืง ืืช ื”ืจืฉืช ื•ืืจืื” ืœืš ืžื” ืžืฆืืชื™. ืžื•ืฆื’ื•ืช ื”ืชื•ืฆืื•ืช ืฉืœ ืคืœื˜ ืคืฉื•ื˜ ื“ืจืš Log.d:

Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true

ืกื•ื’ื™ื™ืช ื”ื”ืชื—ื‘ืจื•ืช ืœืจืฉืช ืžืงื•ื“ ื”ืืคืœื™ืงืฆื™ื” ื ื•ืชืจื” ื‘ืœืชื™ ื ื‘ื“ืงืช. ืื ื™ ืจืง ืื’ื™ื“ ืฉื›ื“ื™ ืœืงืจื•ื ืกื™ืกืžืื•ืช ืฉืžื•ืจื•ืช ืžืžืขืจื›ืช ื”ื”ืคืขืœื” ืฉืœ ืžื›ืฉื™ืจ ื ื™ื™ื“, ืืชื” ืฆืจื™ืš ื–ื›ื•ื™ื•ืช ืฉื•ืจืฉ ื•ื ื›ื•ื ื•ืช ืœื—ื˜ื˜ ื‘ืžืขืจื›ืช ื”ืงื‘ืฆื™ื ื›ื“ื™ ืœืงืจื•ื ืืช wpa_supplicant.conf. ืื ื”ืœื•ื’ื™ืงื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ื“ื•ืจืฉืช ื”ื–ื ืช ืกื™ืกืžื” ืžื‘ื—ื•ืฅ, ื ื™ืชืŸ ืœื™ืฆื•ืจ ืืช ื”ื—ื™ื‘ื•ืจ ื“ืจืš ื”ื›ื™ืชื” android.net.wifi.WifiManager.

ืชื•ื“ื” ืื’ื•ืจ ืคื•ื ื•ืžืจื‘ ืœืชื•ืกืคื•ืช ื™ืงืจื•ืช ืขืจืš.

ืื ืืชื ื—ื•ืฉื‘ื™ื ืฉืฆืจื™ืš ืœื”ื•ืกื™ืฃ ืื• ืœืชืงืŸ ืžืฉื”ื•, ื›ืชื‘ื• ื‘ืชื’ื•ื‘ื•ืช :)

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”