Android全局网络监控最佳实践(Kotlin实现)

本文将介绍如何在Android应用中实现全局网络状态监控,适配高版本API,并提供完整的Kotlin实现方案。

一、核心实现方案

1. 网络监控核心类

kotlin 复制代码
@SuppressLint("MissingPermission")
class NetworkMonitor private constructor(private val context: Context) {
    
    // 网络状态变化回调
    sealed interface NetworkStatus {
        object Available : NetworkStatus
        object Lost : NetworkStatus
        data class Changed(val type: NetworkType) : NetworkStatus
    }

    private val connectivityManager by lazy {
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    }

    private val _networkStatus = MutableSharedFlow<NetworkStatus>()
    val networkStatus = _networkStatus.asSharedFlow()

    private val callback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            postStatus(NetworkStatus.Available)
        }

        override fun onLost(network: Network) {
            postStatus(NetworkStatus.Lost)
        }

        override fun onCapabilitiesChanged(
            network: Network,
            capabilities: NetworkCapabilities
        ) {
            val type = when {
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> 
                    NetworkType.WIFI
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> 
                    NetworkType.CELLULAR
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> 
                    NetworkType.ETHERNET
                else -> NetworkType.UNKNOWN
            }
            postStatus(NetworkStatus.Changed(type))
        }
    }

    fun register() {
        val request = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
            .build()
        
        connectivityManager.registerNetworkCallback(request, callback)
    }

    fun unregister() {
        try {
            connectivityManager.unregisterNetworkCallback(callback)
        } catch (e: IllegalArgumentException) {
            // 忽略未注册的异常
        }
    }

    private fun postStatus(status: NetworkStatus) {
        MainScope().launch {
            _networkStatus.emit(status)
        }
    }

    companion object {
        @Volatile
        private var instance: NetworkMonitor? = null

        fun getInstance(context: Context): NetworkMonitor =
            instance ?: synchronized(this) {
                instance ?: NetworkMonitor(context.applicationContext).also { instance = it }
            }
    }
}

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

2. Application初始化

kotlin 复制代码
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        NetworkMonitor.getInstance(this).register()
    }
}

在AndroidManifest.xml中注册:

xml 复制代码
<application
    android:name=".MyApp"
    ...>
</application>

二、使用示例

1. Activity/Fragment中使用

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    private var networkJob: Job? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        observeNetworkStatus()
    }

    private fun observeNetworkStatus() {
        networkJob = lifecycleScope.launch {
            NetworkMonitor.getInstance(this@MainActivity)
                .networkStatus
                .collect { status ->
                    when (status) {
                        is NetworkMonitor.NetworkStatus.Available -> {
                            showNetworkConnected()
                        }
                        is NetworkMonitor.NetworkStatus.Lost -> {
                            showNetworkDisconnected()
                        }
                        is NetworkMonitor.NetworkStatus.Changed -> {
                            updateNetworkType(status.type)
                        }
                    }
                }
        }
    }

    private fun showNetworkConnected() {
        Toast.makeText(this, "网络已连接", Toast.LENGTH_SHORT).show()
        binding.networkStatusIndicator.setBackgroundColor(Color.GREEN)
    }

    private fun showNetworkDisconnected() {
        Toast.makeText(this, "网络已断开", Toast.LENGTH_SHORT).show()
        binding.networkStatusIndicator.setBackgroundColor(Color.RED)
    }

    private fun updateNetworkType(type: NetworkType) {
        val typeText = when (type) {
            NetworkType.WIFI -> "WiFi网络"
            NetworkType.CELLULAR -> "移动网络"
            NetworkType.ETHERNET -> "有线网络"
            NetworkType.UNKNOWN -> "未知网络"
        }
        binding.networkTypeText.text = "当前网络: $typeText"
    }

    override fun onDestroy() {
        super.onDestroy()
        networkJob?.cancel()
    }
}

2. ViewModel中使用

kotlin 复制代码
class MyViewModel(application: Application) : AndroidViewModel(application) {
    
    private val monitor = NetworkMonitor.getInstance(application)
    
    val networkStatus = monitor.networkStatus
        .stateIn(
            viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = NetworkMonitor.NetworkStatus.Available
        )
}

三、兼容性处理

1. 权限声明

xml 复制代码
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2. 低版本兼容检查

kotlin 复制代码
fun checkNetworkAvailable(): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val activeNetwork = connectivityManager.activeNetwork
        val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
        capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true &&
                capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
    } else {
        @Suppress("DEPRECATION")
        connectivityManager.activeNetworkInfo?.isConnected == true
    }
}

四、高级功能扩展

1. 检测网络质量

kotlin 复制代码
fun getNetworkQuality(): NetworkQuality {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val activeNetwork = connectivityManager.activeNetwork
        val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
        
        return when {
            capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) == false -> 
                NetworkQuality.ROAMING
            capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) == false -> 
                NetworkQuality.METERED
            capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) == false -> 
                NetworkQuality.CONGESTED
            else -> NetworkQuality.GOOD
        }
    }
    return NetworkQuality.UNKNOWN
}

enum class NetworkQuality {
    GOOD, METERED, ROAMING, CONGESTED, UNKNOWN
}

2. 监听特定网络状态

kotlin 复制代码
fun observeWifiStatus(): Flow<Boolean> = networkStatus
    .map { status ->
        when (status) {
            is NetworkStatus.Changed -> status.type == NetworkType.WIFI
            else -> false
        }
    }
    .distinctUntilChanged()

五、最佳实践建议

  1. 生命周期管理:确保在适当的生命周期注册和注销监听
  2. 错误处理:添加适当的异常处理
  3. 线程安全:确保网络状态更新在主线程执行UI操作
  4. 性能优化:避免频繁的网络状态检查
  5. 用户体验:提供友好的网络状态提示

六、总结

本文介绍了Android全局网络监控的完整实现方案,具有以下特点:

  • 使用现代Android API(NetworkCallback)
  • 支持响应式编程(Flow)
  • 提供详细的网络状态信息
  • 良好的兼容性处理
  • 易于扩展的高级功能

这种实现方式适用于大多数现代Android应用,能够有效监控网络状态变化,为用户提供更好的网络体验。

相关推荐
fishwheel14 分钟前
Android:Reverse 实战 part 2 番外 IDA python
android·python·安全
消失的旧时光-19433 小时前
Android网络框架封装 ---> Retrofit + OkHttp + 协程 + LiveData + 断点续传 + 多线程下载 + 进度框交互
android·网络·retrofit
zcychong3 小时前
Handler(二):Java层源码分析
android
Chef_Chen5 小时前
从0开始学习R语言--Day58--竞争风险模型
android·开发语言·kotlin
用户2018792831676 小时前
演员的智能衣橱系统之Selector选择器
android
CYRUS_STUDIO6 小时前
OLLVM 混淆 + VMP 壳照样破!绕过加壳 SDK 的核心检测逻辑
android·逆向·汇编语言
Kapaseker6 小时前
憋了一周了,12000字深入浅出Android的Context机制
android
betazhou6 小时前
MySQL ROUTER安装部署
android·数据库·mysql·adb·mgr·mysql router
用户2018792831676 小时前
🧙‍♂️ 故事:像素王国的“贴纸工厂”与“圣殿徽章工坊”
android