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应用,能够有效监控网络状态变化,为用户提供更好的网络体验。

相关推荐
CYRUS STUDIO19 分钟前
FART 自动化脱壳框架一些 bug 修复记录
android·bug·逆向·fart·脱壳
寻找优秀的自己1 小时前
Cocos 打包 APK 兼容环境表(Android API Level 10~15)
android·cocos2d
大胃粥2 小时前
WMS& SF& IMS: 焦点窗口更新框架
android
QING6182 小时前
Gradle 核心配置属性详解 - 新手指南(二)
android·前端·gradle
QING6182 小时前
Gradle 核心配置属性详解 - 新手指南(一)
android·前端·gradle
_一条咸鱼_5 小时前
Android Runtime内存管理子系统启动流程原理(13)
android·面试·android jetpack
法迪5 小时前
Android的uid~package~pid的关系
android
二流小码农6 小时前
鸿蒙开发:hvigorw,一个你不得不去了解的神器
android·ios·harmonyos
雨白6 小时前
详解三种常见布局:LinearLayout、RelativeLayout及FrameLayout
android