11package io.github.sds100.keymapper.system.network
22
3+ import android.annotation.SuppressLint
34import android.content.ActivityNotFoundException
45import android.content.BroadcastReceiver
56import android.content.Context
@@ -9,11 +10,13 @@ import android.net.ConnectivityManager
910import android.net.Network
1011import android.net.NetworkCapabilities
1112import android.net.NetworkRequest
13+ import android.net.wifi.WifiInfo
1214import android.net.wifi.WifiManager
1315import android.os.Build
1416import android.provider.Settings
1517import android.telephony.SubscriptionManager
1618import android.telephony.TelephonyManager
19+ import androidx.annotation.RequiresApi
1720import androidx.core.content.ContextCompat
1821import androidx.core.content.getSystemService
1922import dagger.hilt.android.qualifiers.ApplicationContext
@@ -74,10 +77,14 @@ class AndroidNetworkAdapter @Inject constructor(
7477
7578 private val isWifiEnabled = MutableStateFlow (isWifiEnabled())
7679
77- private val networkCallback: ConnectivityManager .NetworkCallback =
78- object : ConnectivityManager .NetworkCallback () {
80+ // This requires Android S+ because of the FLAG_INCLUDE_LOCATION_INFO, which is needed
81+ // to get the SSID.
82+ private val networkCallback: ConnectivityManager .NetworkCallback by lazy {
83+ @RequiresApi(Build .VERSION_CODES .S )
84+ object : ConnectivityManager .NetworkCallback (FLAG_INCLUDE_LOCATION_INFO ) {
7985 override fun onAvailable (network : Network ) {
8086 super .onAvailable(network)
87+
8188 isWifiConnected.update { getIsWifiConnected() }
8289 }
8390
@@ -88,6 +95,7 @@ class AndroidNetworkAdapter @Inject constructor(
8895 // If multiple Wi-Fi networks were available and one is lost,
8996 // another might still be active.
9097 isWifiConnected.update { getIsWifiConnected() }
98+ connectedWifiSSIDFlow.update { getWifiSSID() }
9199 }
92100
93101 override fun onCapabilitiesChanged (
@@ -97,8 +105,23 @@ class AndroidNetworkAdapter @Inject constructor(
97105 super .onCapabilitiesChanged(network, networkCapabilities)
98106
99107 isWifiConnected.update { getIsWifiConnected() }
108+
109+ val wifiInfo = networkCapabilities.transportInfo as ? WifiInfo
110+
111+ // Do nothing if this network is not a wifi network
112+ if (wifiInfo == null ) {
113+ return
114+ }
115+
116+ Timber .i(" onCapabilitiesChanged, found SSID: ${wifiInfo.ssid} " )
117+
118+ val ssid = wifiInfo.ssid?.takeIf { it != WifiManager .UNKNOWN_SSID }
119+ ?.removeSurrounding(" \" " )
120+
121+ connectedWifiSSIDFlow.update { ssid }
100122 }
101123 }
124+ }
102125
103126 init {
104127 IntentFilter ().apply {
@@ -113,11 +136,13 @@ class AndroidNetworkAdapter @Inject constructor(
113136 )
114137 }
115138
116- val networkRequest = NetworkRequest .Builder ()
117- .addTransportType(NetworkCapabilities .TRANSPORT_WIFI )
118- .build()
139+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
140+ val networkRequest = NetworkRequest .Builder ()
141+ .addTransportType(NetworkCapabilities .TRANSPORT_WIFI )
142+ .build()
119143
120- connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
144+ connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
145+ }
121146 }
122147
123148 override fun isWifiEnabled (): Boolean = wifiManager.isWifiEnabled
@@ -142,6 +167,7 @@ class AndroidNetworkAdapter @Inject constructor(
142167 }
143168 }
144169
170+ @SuppressLint(" MissingPermission" )
145171 override fun isMobileDataEnabled (): Boolean {
146172 return telephonyManager.isDataEnabled
147173 }
@@ -177,10 +203,20 @@ class AndroidNetworkAdapter @Inject constructor(
177203 /* *
178204 * @return Null on Android 10+ because there is no API to do this anymore.
179205 */
180- override fun getKnownWifiSSIDs (): List <String >? {
206+ @SuppressLint(" MissingPermission" )
207+ override fun getKnownWifiSSIDs (): List <String > {
181208 if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
182- return null
209+ // On Android Q and above, apps can't access the list of configured Wi-Fi networks.
210+ // As a fallback, we return the currently connected network's SSID.
211+ val ssid = getWifiSSID()
212+
213+ return if (ssid != null ) {
214+ listOf (ssid)
215+ } else {
216+ emptyList()
217+ }
183218 } else {
219+ @Suppress(" DEPRECATION" )
184220 return wifiManager.configuredNetworks?.map {
185221 it.SSID .removeSurrounding(" \" " )
186222 } ? : emptyList()
@@ -250,6 +286,9 @@ class AndroidNetworkAdapter @Inject constructor(
250286 }
251287
252288 private fun getIsWifiConnected (): Boolean {
289+ @Suppress(" DEPRECATION" )
290+ // The deprecation notice is advice to use the callback instead. getAllNetworks() still
291+ // functions
253292 return connectivityManager.allNetworks.any { network ->
254293 connectivityManager.getNetworkCapabilities(network)
255294 ?.hasTransport(NetworkCapabilities .TRANSPORT_WIFI ) ? : false
0 commit comments