Wi-Fi eta beste hainbat laburdura. Nola lortu Wi-Fi nodoei buruzko datuak Android aplikazio batean puztu gabe

Egun batean Android aplikazioetatik Wi-Fi sareak eskaneatu eta sarbide puntuei buruzko datu zehatzak lortu behar izan nituen.

Hemen hainbat zailtasunei aurre egin behar izan diegu: off.Android dokumentazioa deskribatutako klase asko zaharkituta geratu ziren (API maila > 26), eta hori ez zen bertan islatzen; dokumentazioan gauza batzuen deskribapena gutxienekoa da (adibidez, klaseko gaitasunen eremua ScanResult idazteko unean, ia ezer ez da deskribatzen, datu garrantzitsu asko dituen arren). Hirugarren zailtasuna izan daiteke Wi-Fira lehen aldiz hurbiltzen zarenean, teoria irakurri eta localhost bidez bideratzailea konfiguratzeaz gain, banan-banan ulergarriak diruditen hainbat laburdurari aurre egin behar diezula. Baina baliteke horiek nola erlazionatu eta egituratu (juizioa subjektiboa da eta aurreko esperientziaren araberakoa da).

Artikulu honek Wi-Fi inguruneari buruzko datu integralak nola lortu aztertzen du Android kodetik NDK, hackik gabe, baina Android APIa erabiliz soilik eta nola interpretatu ulertzen.

Ez gaitezen atzeratu eta has gaitezen kodea idazten.

1. Proiektu bat sortu

Ohar hau Android proiektu bat behin baino gehiagotan sortu dutenentzat pentsatuta dago, beraz, elementu honen xehetasunak baztertzen ditugu. Beheko kodea Kotlin-en aurkeztuko da, minSdkVersion=23.

2. Sarbide-baimenak

Aplikaziotik Wi-Fi-arekin lan egiteko, erabiltzailearen hainbat baimen lortu beharko dituzu. -ren arabera dokumentazioa, 8.0-tik aurrera OS bertsioak dituzten gailuetan sarea eskaneatzeko, sare-ingurunearen egoera ikusteko sarbidea izateaz gain, gailuaren Wi-Fi moduluaren egoera aldatzeko sarbidea behar duzu, edo koordenatuetarako sarbidea (gutxi gorabehera). edo zehatza). 9.0 bertsiotik hasita, biak eskatu behar dizkiozu erabiltzaileari, eta kokapen-zerbitzuak aktibatzeko espresuki ere eskatu behar diozu erabiltzaileari. Ez ahaztu erabiltzaileari ausarki azaltzea Googleren kapritxoa dela, eta ez zelatatzeko gogoa :)

Beraz, AndroidManifest.xml-n gehituko dugu:

    <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"/>

Eta uneko Jarduerarako esteka duen kodean:

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. Sortu Broadcast Receiver eta harpidetu Wi-Fi sarearen ingurunea eskaneatzeari buruzko datuak eguneratzeko ekitaldietara.

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
}

Dokumentazioko WiFiManager.startScan metodoa deskargatu gisa markatuta dago APIaren 28 bertsiotik, baina desaktibatuta dago. gidatuko erabiltzea proposatzen du.

Guztira, objektuen zerrenda jaso dugu ScanResult.

4. Begiratu ScanResult-i eta ulertu terminoak

Ikus ditzagun klase honetako eremu batzuk eta deskriba ditzagun zer esan nahi duten:

SSID β€” Service Set Identifier sarearen izena da

BSSID - Oinarrizko zerbitzu multzoaren identifikatzailea - sare-egokitzailearen MAC helbidea (Wi-Fi puntua)

maila β€” Jasotako seinalearen indarraren adierazlea [dBm (errusiako dBm) β€” Dezibelioa, erreferentzia-potentzia 1 mW.] β€” Jasotako seinalearen indarraren adierazlea. 0tik -100 arteko balioa hartzen du, zenbat eta 0tik urrunago, orduan eta seinale potentzia gehiago galdu da Wi-Fi puntutik zure gailurako bidean. Xehetasun gehiago aurki daitezke, adibidez, helbidean Wikipedia. Hemen esango dizut Android klasea erabiliz Wifi Manager seinale-maila bikainetik izugarrirako eskala batean kalibratu dezakezu aukeratzen duzun urratsean:

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

maiztasuna β€” Wi-Fi puntuaren funtzionamendu-maiztasuna [Hz]. Maiztasunaz gain, kanala deiturikoa interesatzen zaizu. Puntu bakoitzak bere funtzionamendu-garbitasuna du. Idazteko unean, Wi-Fi puntuen gamarik ezagunena 2.4 GHz da. Baina, zehatzago esateko, puntuak zure telefonora igortzen du informazioa izena duenetik hurbil dagoen zenbakidun maiztasun batean. Kanal kopurua eta dagozkion maiztasunak normalizatua. Honen bidez, gertuko puntuek maiztasun ezberdinetan funtziona dezaten egiten da, horrela elkarren artean oztopatzeko eta transmisioaren abiadura eta kalitatea elkarren artean murrizteko. Kasu honetan, puntuek ez dute maiztasun batean funtzionatzen, maiztasun tarte batean baizik (parametroa kanalaren zabalera), kanalaren zabalera izenekoa. Hau da, ondoko kanaletan (eta ez bakarrik aldamenean, baita berez 3 ere) diharduten puntuek elkar oztopatzen dute. Baliteke kode sinple hau erabilgarria izatea, kanalaren zenbakia 2.4 eta 5 Ghz-ko maiztasuna duten puntuen maiztasun-balioaren arabera kalkulatzeko aukera ematen duena:


    /* ΠΏΠΎ частотС опрСдСляСм Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ°Π½Π°Π»Π° */
    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
            }
        }

gaitasun - analisirako arlorik interesgarriena, denbora asko behar izan duen lana. Hemen puntuaren "gaitasunak" lerroan idatzita daude. Kasu honetan, ez duzu dokumentazioan kateen interpretazioaren xehetasunak bilatu beharrik. Hona hemen lerro honetan egon daitekeenaren adibide batzuk:

[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. Laburdurak eta analizatzeko gaitasunak ulertzea

Aipatzekoa da Android.net.wifi.* paketearen klaseak Linux utilitate batek kaputxa azpian erabiltzen dituela. wpa_eskatzailea eta gaitasunen eremuko irteerako emaitza banderak eremuaren kopia bat da eskaneatzean.

Koherentziaz jokatuko dugu. Har dezagun lehenik parentesi barruko elementuak β€œ-β€œ zeinu batez bereizten diren formatu baten irteera:

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

Lehenengo esanahiak deiturikoak deskribatzen ditu. autentifikazio metodoa. Hau da, zer ekintzen sekuentzia egin behar duten gailuak eta sarbide-puntuak sarbide-puntuak bere burua erabiltzeko eta nola enkriptatu karga erabilgarria izateko. Post hau idazteko momentuan, aukerarik ohikoenak WPA eta WPA2 dira, zeinetan konektatutako gailu bakoitza zuzenean edo deitzen denaren bidez. RADIUS zerbitzariak (WPA-Enterprice) enkriptatutako kanal baten bidez ematen du pasahitza. Seguruenik, zure etxeko sarguneak eskema honen araberako konexioa eskaintzen du. Bigarren bertsioaren eta lehenengoaren arteko aldea zifratze indartsuagoa duela da: AES versus TKIP segurua. WPA3 ere, konplexuagoa eta aurreratuagoa dena, pixkanaka sartzen ari da. Teorian, aukera bat egon daiteke CCKM (Cisco Centralized Key Management) enterprice irtenbidearekin, baina ez dut inoiz topatu.

Baliteke sarbide-puntua MAC helbidearen bidez autentifikatzeko konfiguratuta egotea. Edo, sarbide-puntuak WEP algoritmo zaharkitua erabiliz datuak ematen baditu, egia esan ez dago autentifikaziorik (gako sekretua hemen enkriptatze-gakoa da). Bestelako aukerak bezala sailkatzen ditugu.
Wi-fi publikoan ezaguna den metodo bat ere badago ezkutuko Atari Gatibuen Detekzioarekin: arakatzaile baten bidez autentifikazio eskaera. Sarbide horiek irekita agertzen zaizkio eskanerari (konexio fisikoaren ikuspuntutik dira). Horregatik, IREKI gisa sailkatzen ditugu.

Bigarren balioa honela adieraz daiteke gakoak kudeatzeko algoritmoa. Hau goian deskribatutako autentifikazio metodoaren parametro bat da. Zifratze-gakoak nola trukatzen diren zehatz-mehatz hitz egiten du. Azter ditzagun aukera posibleak. EAP - aipatutako WPA-Enterprice-n erabiltzen dena, datu-base bat erabiltzen du sartutako autentifikazio-datuak egiaztatzeko. SAE - WPA3 aurreratuan erabiltzen da, indar gordinaren aurrean erresistenteagoa. PSK - aukerarik ohikoena, pasahitz bat sartu eta enkriptatutako forman transmititzea dakar. IEEE8021X - nazioarteko estandar baten arabera (WPA familiak onartzen duenaren ezberdina). OWE (Opportunistic Wireless Encryption) IEEE 802.11 estandarraren luzapena da OPEN gisa sailkatu ditugun puntuetarako. OWE-k segurtasunik gabeko sare baten bidez transmititzen diren datuen segurtasuna bermatzen du, enkriptatuz. Aukera bat ere posible da sarbide-gakorik ez dagoenean, dei diezaiogun EZER aukera honi.

Hirugarren parametroa izenekoa da. enkriptatzeko eskemak β€” nola erabiltzen den zifratua transmititutako datuak babesteko. Zerrenda ditzagun aukerak. WEP - RC4 korronte zifratua erabiltzen du, gako sekretua enkriptatze-gakoa da, kriptografia modernoaren munduan onartezina dena. TKIP - WPAn erabiltzen da, CKIP - WPA2n. TKIP+CKIP - WPA eta WPA2 gai diren puntuetan zehaztu daiteke atzerako bateragarritasunerako.

Hiru elementuren ordez, WEP marka bakarti bat aurki dezakezu:

[WEP]

Goian aipatu dugun bezala, nahikoa da gakoak erabiltzeko algoritmoa, existitzen ez dena, eta enkriptatzeko metodoa, lehenespenez berdina dena.

Orain kontuan hartu parentesi hau:

[ESS]

It Wi-Fi funtzionamendu modua edo Wi-Fi sarearen topologia. BSS (Oinarrizko Zerbitzu multzoa) modua aurki dezakezu - konektatutako gailuak komunikatzeko sarbide puntu bat dagoenean. Sare lokaletan aurki daiteke. Oro har, sarbide-puntuak behar dira sare lokal ezberdinetako gailuak konektatzeko, beraz, Zerbitzu Hedatuen Multzoen - ESSren parte dira. IBSSak (Independent Basic Service Sets) motak adierazten du gailua Peer-to-Peer sare baten parte dela.

WPS bandera ere ikus dezakezu:

[WPS]

WPS (Wi-Fi Protected Setup) Wi-Fi sare baten hasierako hasierako protokoloa da. Hasieratzeko, erabiltzaileak 8 karaktereko pasahitza sartzen du edo bideratzailearen botoi bat sakatzen du. Zure sarbide-puntua lehen motakoa bada eta kontrol-lauki hau zure sarbide-puntuaren izenaren ondoan agertzen bada, gomendagarria da administrazio panelera joatea eta WPS sarbidea desgaitzea. Kontua da askotan 8 digituko PINa MAC helbidearen bidez aurki daitekeela, edo aurreikusten den denbora batean konpondu daitekeela, norbaitek desleialki aprobetxa dezakeela.

6. Sortu eredua eta analisi-funtzioa

Goian aurkitu dugunaren arabera, datu klaseak erabiliz gertatutakoa deskribatuko dugu:

/* схСма Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ */
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.
}

Orain idatz dezagun gaitasunen eremua analizatuko duen funtzio bat:


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. Ikusi emaitza

Sarea eskaneatu eta aurkitu dudana erakutsiko dizut. Log.d bidezko irteera sinplearen emaitzak erakusten dira:

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

Aplikazio-kodetik sarera konektatzearen arazoa aztertu gabe geratu zen. Bakarrik esango dut gailu mugikor baten OStik gordetako pasahitzak irakurtzeko, root eskubideak eta wpa_supplicant.conf irakurtzeko fitxategi-sisteman arakatzeko borondatea behar dituzula. Aplikazioaren logikak kanpotik pasahitz bat sartzea eskatzen badu, konexioa klasearen bidez egin daiteke android.net.wifi.WifiManager.

Eskerrik asko Egor Ponomarev gehigarri baliotsuetarako.

Zerbait gehitu edo zuzendu behar dela uste baduzu, idatzi iruzkinetan :)

Iturria: www.habr.com

Gehitu iruzkin berria