You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android NetworkCallback网络状态监听无回调问题排查

Android 网络状态监听无回调问题解决方案

问题背景

开发Android网络状态监听示例应用时,参考官方文档实现了ConnectivityManager.NetworkCallback监听逻辑,出现以下异常:

  • 设备已联网状态启动应用:onAvailable --- CALLED、onCapabilitiesChanged --- CALLED、onLost --- CALLED日志均可正常输出,回调触发符合预期
  • 设备断网状态启动应用:启动时无任何日志输出,后续手动开启网络连接也不会触发任何回调

现有实现代码

MainActivity.kt

package me.soft.network

import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    lateinit var networkRequest: NetworkRequest
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        // 网络可用
        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            println("onAvailable --- CALLED")
        }

        // 网络能力变更
        override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
        ) {
            super.onCapabilitiesChanged(network, networkCapabilities)
            val unmetered = networkCapabilities.hasCapability(NetworkCapabilities.  NET_CAPABILITY_NOT_METERED)
            println("onCapabilitiesChanged --- CALLED")
        }

        // 网络连接丢失
        override fun onLost(network: Network) {
            super.onLost(network)
            println("onLost --- CALLED")
        }
    }


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

        networkRequest = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .build()

        val connectivityManager = getSystemService(ConnectivityManager::class.java) as  ConnectivityManager
        connectivityManager.requestNetwork(networkRequest, networkCallback)
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="me.soft.network">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NetWork"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

错误原因

  1. API误用:代码中调用的requestNetwork()方法设计目标是主动向系统申请建立一条符合NetworkRequest规则的网络连接,属于主动发起网络请求的API,不是用于被动监听全局网络状态的API。当启动应用时无可用网络,该方法不会持续驻留等待后续网络连接,因此后续联网时不会触发回调。
  2. 缺少回调反注册逻辑:当前代码仅在onCreate中注册回调,未在页面销毁时反注册,会造成内存泄漏,极端场景下会触发崩溃。
  3. 代码中NetworkCapabilities. NET_CAPABILITY_NOT_METERED存在多余空格,虽不影响编译,但属于不规范写法。

修正方案

  1. 将requestNetwork()替换为专门用于网络状态监听的registerNetworkCallback()方法,该方法会持续监听符合规则的网络状态变化,不受启动时网络状态影响。
  2. 在onDestroy生命周期中调用unregisterNetworkCallback()反注册回调,避免内存泄漏。
  3. 修正代码中的多余空格问题。

修正后核心代码

class MainActivity : AppCompatActivity() {
    private lateinit var networkRequest: NetworkRequest
    private lateinit var connectivityManager: ConnectivityManager
    
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            println("onAvailable --- CALLED")
        }

        override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
        ) {
            super.onCapabilitiesChanged(network, networkCapabilities)
            val unmetered = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
            println("onCapabilitiesChanged --- CALLED, unmetered: $unmetered")
        }

        override fun onLost(network: Network) {
            super.onLost(network)
            println("onLost --- CALLED")
        }
    }


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

        networkRequest = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .build()

        connectivityManager = getSystemService(ConnectivityManager::class.java)
        // 替换为注册网络监听的API
        connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
    }

    override fun onDestroy() {
        // 反注册回调避免内存泄漏
        connectivityManager.unregisterNetworkCallback(networkCallback)
        super.onDestroy()
    }
}

可选优化

如果应用的最低支持版本为Android 7.0(API 24)及以上,可以直接使用registerDefaultNetworkCallback()方法,无需手动构建NetworkRequest,会自动监听系统当前默认的活跃网络,代码更简洁:

// 替换registerNetworkCallback即可,不需要提前构建networkRequest
connectivityManager.registerDefaultNetworkCallback(networkCallback)

内容的提问来源于stack exchange,提问作者Michel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 15:18:15