睿诚科技协会

Android如何监听网络状态变化?

在Android开发中,监听网络状态是一项常见且重要的功能,它能够帮助应用根据当前网络连接情况(如Wi-Fi、移动数据、无网络等)调整行为,例如在无网络时提示用户、在有网络时自动同步数据等,Android系统提供了多种方式来实现网络状态监听,主要包括ConnectivityManager、NetworkCallback以及BroadcastReceiver等,下面将详细介绍这些方法的实现原理、使用场景及注意事项。

Android如何监听网络状态变化?-图1
(图片来源网络,侵删)

使用ConnectivityManager与NetworkInfo(已废弃,但需了解)

在Android 6.0(API 23)之前,通常通过ConnectivityManager的getNetworkInfo()方法获取NetworkInfo对象,进而判断网络状态。

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
    // 网络可用
} else {
    // 网络不可用
}

但此方法已在API 23中被标记为废弃,因为其无法实时监听网络变化,且无法精确区分网络类型(如Wi-Fi或移动数据),目前仅适用于兼容旧版本代码的场景。

使用BroadcastReceiver监听网络变化(静态注册与动态注册)

动态注册(推荐)

通过注册一个BroadcastReceiver来监听系统广播ConnectivityManager.CONNECTIVITY_ACTION,当网络状态变化时,系统会发送此广播,示例代码如下:

private BroadcastReceiver networkReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
                // 网络已连接
            } else {
                // 网络断开
            }
        }
    }
};
// 在Activity或Service中注册
registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
// 务必在适当时候注销(如Activity的onDestroy中)
unregisterReceiver(networkReceiver);

优点:兼容性较好,支持Android 6.0以下版本。
缺点:静态注册(在AndroidManifest.xml中注册)在Android 8.0(API 26)后无法接收隐式广播,动态注册需手动管理生命周期。

Android如何监听网络状态变化?-图2
(图片来源网络,侵删)

静态注册(仅限Android 8.0以下)

在AndroidManifest.xml中声明:

<receiver android:name=".NetworkChangeReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

注意:Android 8.0及以上系统限制后台应用接收静态广播,因此不推荐在新项目中使用。

使用NetworkCallback(推荐,API 21+)

Android 5.0(API 21)引入了NetworkCallback机制,通过ConnectivityManager的requestNetwork()或registerNetworkCallback()方法注册回调,可以更精确地监听网络状态变化,并支持网络能力的细粒度判断(如网络类型、带宽等),示例代码如下:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest networkRequest = new NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build();
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        // 网络可用
    }
    @Override
    public void onLost(Network network) {
        // 网络丢失
    }
    @Override
    public void onUnavailable() {
        // 网络不可用
    }
};
// 注册回调
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
// 注销回调(需在Activity/Service销毁时调用)
connectivityManager.unregisterNetworkCallback(networkCallback);

优点:支持实时回调、精确判断网络类型、性能更优(无需通过广播机制)。
缺点:仅适用于API 21及以上版本,需处理版本兼容性。

Android如何监听网络状态变化?-图3
(图片来源网络,侵删)

网络状态判断的常见场景与代码示例

场景 实现方法
判断是否有网络连接 使用NetworkCallback的onAvailable()或BroadcastReceiver的isActiveNetworkInfo()
判断是否为Wi-Fi 通过NetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
判断是否为移动数据 通过NetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
获取当前网络类型 NetworkCapabilities.getNetworkType()或NetworkInfo.getType()

注意事项

  1. 权限申请:需在AndroidManifest.xml中声明网络权限:
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
  2. 后台网络限制:Android 6.0以上系统在后台运行时可能限制网络访问,需考虑JobScheduler或WorkManager处理后台网络任务。
  3. 网络切换处理:当网络从Wi-Fi切换到移动数据时,需确保应用能正确处理数据量或资费问题。

相关问答FAQs

问题1:为什么在Android 8.0及以上版本使用静态注册的BroadcastReceiver无法监听网络变化?
解答:从Android 8.0开始,系统对后台应用接收隐式广播进行了限制,以减少电量消耗和提升系统性能,静态注册的BroadcastReceiver属于隐式广播,因此无法在后台被正常触发,建议改用动态注册或NetworkCallback(API 21+)的方式监听网络变化。

问题2:如何区分当前网络是Wi-Fi还是移动数据?
解答:在NetworkCallback中,可以通过NetworkCapabilities的getTransportType()方法判断,

@Override
public void onAvailable(Network network) {
    NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
    if (capabilities != null) {
        if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            // 当前为Wi-Fi
        } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            // 当前为移动数据
        }
    }
}
分享:
扫描分享到社交APP
上一篇
下一篇