【Android】Wifi情報を一覧表示する

KotlinでWifiの情報(SSIDなど)をスキャンして一覧表示するアプリを作ってみた。

作ってみたアプリ。

比較的シンプルなコードで実装できたので作り方を紹介したい。

パーミッションの取得

Wifi情報を得るには以下のパーミッション達を得る必要がある。

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

なぜ、Wifiなのに位置情報のアクセス権限が必要なのか疑問であったが、どうやらWifiのBSSIDと電波強度データで位置情報を特定可能になるようです。

https://gigazine.net/news/20150608-how-apps-track-location/

次にパーミッションを得るためのコードを紹介する。

    private val PERMISSIONS_REQUEST_CODE = 1
    private val wifiManager: WifiManager get() = this.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

    //パーミッション取得状態を確認し、パーミッションリクエストを出す。
    //パーミッションが得られている状態であれば、Wifiの情報を取得する。
    private fun checkPermissionAndRequest(){
        if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
            checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        ) {
            requestPermissions(
                arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                PERMISSIONS_REQUEST_CODE))
        }else{
            // 許可済みの処理
            getScanResult()
        }
    }

パーミッションが取得できているか確認し、取得できていればWifi情報をスキャンする関数getScanResultを実行する。この関数の中身については後ほど説明する。

requestPermissions関数が実行されると、以下のように確認ダイアログが表示される。

すでにパーミッションが使用中に許可されている場合には、ダイアログは表示されない。

Android12の位置情報取得パーミッションダイアログ。(Pexel 6a)

Android12で実行した結果だが、円形の画像がカッコいい。

「While using the app」か「Only this time」を選択すると、許可されたことになる。

「While using the app」「Deny」を選択すると、次回起動時には確認ダイアログが出ない。

確認ダイアログを毎回表示させたい場合には、「Only this time」を選択する。

選択した後に呼ばれる関数を作っておく。

    //パーミッションリクエストダイアログでユーザが選択した後に呼ばれる。
    override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array<String>, @NonNull grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode != PERMISSIONS_REQUEST_CODE) {
            return
        }
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 許可した時の処理
            getScanResult()
        }
    }

これを作っておかないと、ユーザが許可もしくは拒否を選択した後に、getScanResultが実行されない。

ListViewでListの中身を一覧表示する

最後にスキャン結果を取得して、ListViewにセットする。

    // Wifiのスキャン結果を取得し、ListViewにセットする。
    private fun getScanResult(){
        if (wifiManager.wifiState == WifiManager.WIFI_STATE_ENABLED) {
            val results = wifiManager.scanResults
            println("hoge$results")
            list_view.adapter = ArrayAdapter(
                this,
                android.R.layout.simple_list_item_1,
                results
            )
        }
    }

ListViewを使うと、上記のコードだけでListの内容を羅列できる。

ArrayAdapterを使ってListを指定する。

ListViewはPaletteで検索すると出てくるので配置した。

ScanResultで取得できる情報

API32の時点で、ScanResultで取れる情報をご紹介する。

  • SSID:ネットワークのID
  • BSSID:アクセスポイントのMACアドレス
  • capabilities:暗号化情報
  • frequency:周波数(Mhz)
  • level:信号レベル(dBm)

周波数は2442のように4桁の数字で取れるのでそのままだと分かりづらい。

Githubにあったチャンネルの変換情報テーブルを利用し”ch 7 – 2.4ghz”ように変換する。

https://gist.github.com/Dantali0n/601702efe04665a3a59d

また、信号レベルについても、-43のように分かりづらいので5段階のレベルに変換すると良い。

val level5: Int = WifiManager.calculateSignalLevel(level, 5)

API32だとcalculateSignalLevelはDeprecatedで非推奨だが気にしないことにする。

その他の情報についてはAndroid開発者ページをご参考ください。

https://developer.android.com/reference/android/net/wifi/ScanResult

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog