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で実行した結果だが、円形の画像がカッコいい。
「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