@@ -7,16 +7,12 @@ import android.net.wifi.WifiManager
77import android.os.Build
88import androidx.core.content.ContextCompat
99import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
10- import androidx.lifecycle.LiveData
11- import kotlinx.coroutines.*
12- import net.kuama.wifiMonitor.data.WiFiInfo
13- import net.kuama.wifiMonitor.data.WifiNetworkBand
14- import net.kuama.wifiMonitor.data.WifiState
10+ import kotlinx.coroutines.Dispatchers
11+ import kotlinx.coroutines.withContext
12+ import net.kuama.wifiMonitor.data.WifiStatus
1513import net.kuama.wifiMonitor.implementation.AndroidQWifiListener
1614import net.kuama.wifiMonitor.implementation.BeforeAndroidQWifiListener
1715
18- private fun noop () {}
19-
2016class WifiMonitor (context : Context ) {
2117
2218 private val listener = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
@@ -26,94 +22,75 @@ class WifiMonitor(context: Context) {
2622 BeforeAndroidQWifiListener (context)
2723 }
2824
29- private val scope = CoroutineScope (SupervisorJob () + Dispatchers .Default )
30-
3125 private val wifiManager: WifiManager =
3226 context.applicationContext.getSystemService(Context .WIFI_SERVICE ) as WifiManager
3327
34- fun stop () = listener.stop()
35-
36- fun start (onChange : () -> Unit ) = scope.launch { listener.start(onChange) }
37-
38- val state: Int
39- get() = wifiManager.wifiState
40-
41- val connectionInfo: WifiInfo
42- get() = wifiManager.connectionInfo
43-
44- val isFineLocationAccessGranted = ContextCompat .checkSelfPermission(
45- context,
46- Manifest .permission.ACCESS_FINE_LOCATION
47- ) == PERMISSION_GRANTED
48- }
49-
50- class WifiLiveData constructor(private val monitor : WifiMonitor ) :
51- LiveData <WiFiInfo >() {
52-
53- private var startJob: Job ? = null
54-
55- override fun onActive () {
56- super .onActive()
57- startJob = monitor.start(::onWifiChange)
58- }
59-
60- override fun onInactive () {
61- super .onInactive()
62- if (startJob?.isActive == true ) {
63- startJob?.cancel()
64- }
65- monitor.stop()
66- }
67-
6828 /* *
69- * Will check the current wifi state and propagate different infos
70- * based on it.
29+ * Whether we received at least a Wi-Fi change status. When false, we cannot say we are connected
7130 */
72- private fun onWifiChange () {
73- when (monitor.state) {
74- WifiManager .WIFI_STATE_DISABLED , WifiManager .WIFI_STATE_DISABLING -> onWifiDisabled()
75- WifiManager .WIFI_STATE_ENABLED -> onWifiEnabled(monitor.connectionInfo)
76- WifiManager .WIFI_STATE_ENABLING -> noop()
77- else -> onCouldNotGetWifiState()
78- }
79- }
31+ private var didReceiveChange = false
8032
8133 /* *
82- * Propagates a [WifiState.DISCONNECTED] state
34+ * Stop listening to Wi-Fi changes
8335 */
84- private fun onWifiDisabled () = postValue( WiFiInfo ( WifiState . DISCONNECTED ) )
36+ fun stop () = listener.stop( )
8537
8638 /* *
87- * Propagates a [WifiState.CONNECTED] state, and the
88- * current wi-fi ssid (if android.permission.ACCESS_FINE_LOCATION was granted,
89- * <unknown-ssid> otherwise)
39+ * Triggers the on change callback whenever the Wi-Fi changes its status
9040 */
91- private fun onWifiEnabled (connectionInfo : WifiInfo ) {
41+ suspend fun observe (onChange : (WifiStatus ) -> Unit ) =
42+ withContext(Dispatchers .Default ) {
43+ listener.start {
44+ didReceiveChange = true
45+ onChange(info)
46+ }
47+ }
48+
49+ private val state: Int
50+ get() = wifiManager.wifiState
51+
52+ private val connectionInfo: WifiInfo
53+ get() = wifiManager.connectionInfo
9254
93- val band = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
55+ private val band: WifiStatus .NetworkBand
56+ get() = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
9457 if (connectionInfo.frequency > 3000 ) {
95- WifiNetworkBand .WIFI_5_GHZ
58+ WifiStatus . NetworkBand .WIFI_5_GHZ
9659 } else {
97- WifiNetworkBand .WIFI_2_4_GHZ
60+ WifiStatus . NetworkBand .WIFI_2_4_GHZ
9861 }
9962 } else {
100- WifiNetworkBand .UNKNOWN
63+ WifiStatus . NetworkBand .UNKNOWN
10164 }
10265
103- postValue(
104- WiFiInfo (
105- state = if (monitor.isFineLocationAccessGranted) WifiState .CONNECTED else WifiState .CONNECTED_MISSING_FINE_LOCATION_PERMISSION ,
106- ssid = connectionInfo.ssid,
107- bssid = connectionInfo.bssid,
108- band = band,
109- rssi = connectionInfo.rssi
110- )
111- )
112- }
66+ /* *
67+ * Holds the current information on the Wi-Fi connection.
68+ */
69+ val info: WifiStatus
70+ get() = if (didReceiveChange) {
71+ when (state) {
72+ WifiManager .WIFI_STATE_DISABLED , WifiManager .WIFI_STATE_DISABLING -> WifiStatus (
73+ WifiStatus .State .DISCONNECTED
74+ )
75+ WifiManager .WIFI_STATE_ENABLED -> WifiStatus (
76+ state = if (isFineLocationAccessGranted) WifiStatus .State .CONNECTED else WifiStatus .State .CONNECTED_MISSING_FINE_LOCATION_PERMISSION ,
77+ ssid = connectionInfo.ssid,
78+ bssid = connectionInfo.bssid,
79+ band = band,
80+ rssi = connectionInfo.rssi
81+ )
82+ WifiManager .WIFI_STATE_ENABLING -> WifiStatus (WifiStatus .State .ENABLING )
83+ else -> WifiStatus (WifiStatus .State .UNKNOWN )
84+ }
85+ } else {
86+ WifiStatus (WifiStatus .State .UNKNOWN )
87+ }
11388
11489 /* *
115- * Propagates a [WifiState.UNKNOWN] state.
116- * Typically it's the first value that gets emitted to the subscribers
90+ * True if the user granted access to [Manifest.permission.ACCESS_FINE_LOCATION]
11791 */
118- private fun onCouldNotGetWifiState () = postValue(WiFiInfo (WifiState .UNKNOWN ))
92+ val isFineLocationAccessGranted: Boolean = ContextCompat .checkSelfPermission(
93+ context,
94+ Manifest .permission.ACCESS_FINE_LOCATION
95+ ) == PERMISSION_GRANTED
11996}
0 commit comments