Skip to content

Implement Network Reachability Monitoring for Offline Handling #9995

@sanchitmonga22

Description

@sanchitmonga22

Priority

LOW

Context

Network Reachability monitoring detects network state changes and enables offline-first behavior. The iOS SDK has NWPathMonitor integration. The Kotlin SDK is missing this infrastructure.

Current State

  • Status: No reachability monitoring
  • Impact: Cannot adapt to network state changes
  • iOS Has: Network monitoring with NWPathMonitor

iOS Reference Implementation

  • Service: Network monitoring using NWPathMonitor

Implementation Plan

1. Define Common Interfaces (commonMain)

// commonMain/kotlin/com/runanywhere/sdk/infrastructure/network/NetworkReachability.kt
interface NetworkReachability {
    val isReachable: Boolean
    val networkType: NetworkType
    val reachabilityFlow: Flow<NetworkState>
}

enum class NetworkType {
    NONE, WIFI, CELLULAR, ETHERNET
}

data class NetworkState(
    val isReachable: Boolean,
    val type: NetworkType,
    val timestamp: Long
)

2. Platform Implementations

Android (androidMain)

// androidMain/kotlin/com/runanywhere/sdk/infrastructure/network/AndroidNetworkReachability.kt
class AndroidNetworkReachability(
    private val context: Context
) : NetworkReachability {
    
    private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    private val _reachabilityFlow = MutableStateFlow(getCurrentNetworkState())
    override val reachabilityFlow: StateFlow<NetworkState> = _reachabilityFlow.asStateFlow()
    
    init {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network) {
                    _reachabilityFlow.value = getCurrentNetworkState()
                }
                
                override fun onLost(network: Network) {
                    _reachabilityFlow.value = getCurrentNetworkState()
                }
            })
        }
    }
    
    override val isReachable: Boolean
        get() = connectivityManager.activeNetworkInfo?.isConnected == true
    
    override val networkType: NetworkType
        get() {
            val activeNetwork = connectivityManager.activeNetworkInfo
            return when (activeNetwork?.type) {
                ConnectivityManager.TYPE_WIFI -> NetworkType.WIFI
                ConnectivityManager.TYPE_MOBILE -> NetworkType.CELLULAR
                ConnectivityManager.TYPE_ETHERNET -> NetworkType.ETHERNET
                else -> NetworkType.NONE
            }
        }
    
    private fun getCurrentNetworkState(): NetworkState {
        return NetworkState(
            isReachable = isReachable,
            type = networkType,
            timestamp = System.currentTimeMillis()
        )
    }
}

JVM (jvmMain)

// jvmMain/kotlin/com/runanywhere/sdk/infrastructure/network/JvmNetworkReachability.kt
class JvmNetworkReachability : NetworkReachability {
    
    private val _reachabilityFlow = MutableStateFlow(getCurrentNetworkState())
    override val reachabilityFlow: StateFlow<NetworkState> = _reachabilityFlow.asStateFlow()
    
    init {
        // Poll network state periodically
        CoroutineScope(Dispatchers.IO).launch {
            while (true) {
                delay(5000) // Check every 5 seconds
                _reachabilityFlow.value = getCurrentNetworkState()
            }
        }
    }
    
    override val isReachable: Boolean
        get() {
            return try {
                val url = URL("https://www.google.com")
                val connection = url.openConnection()
                connection.connectTimeout = 3000
                connection.connect()
                true
            } catch (e: Exception) {
                false
            }
        }
    
    override val networkType: NetworkType
        get() = if (isReachable) NetworkType.ETHERNET else NetworkType.NONE
    
    private fun getCurrentNetworkState(): NetworkState {
        return NetworkState(
            isReachable = isReachable,
            type = networkType,
            timestamp = System.currentTimeMillis()
        )
    }
}

Files to Create/Modify

New Files (commonMain)

  • infrastructure/network/NetworkReachability.kt
  • infrastructure/network/models/NetworkState.kt
  • infrastructure/network/models/NetworkType.kt

New Files (androidMain)

  • infrastructure/network/AndroidNetworkReachability.kt

New Files (jvmMain)

  • infrastructure/network/JvmNetworkReachability.kt

Files to Modify

  • foundation/ServiceContainer.kt (add network reachability)

Testing Requirements

  • Unit tests for network state detection
  • Integration tests with network state changes
  • Android platform tests
  • JVM platform tests

Success Criteria

  • Correctly detects network state changes
  • Android implementation uses ConnectivityManager
  • JVM implementation has periodic checking
  • Flow emits state changes
  • Integrated into ServiceContainer

Estimated Effort

3-5 days

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidIssue doesn't seem to be related to Claude Code

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions