睿诚科技协会

android 网络类型判断

  1. 连接状态:设备是否连接到了网络(任何类型)。
  2. 网络类型:设备连接的是哪种具体的网络,如 Wi-Fi、移动数据(2G/3G/4G/5G)、以太网等。

下面我将详细介绍如何实现这两种判断,并提供完整的代码示例。

android 网络类型判断-图1
(图片来源网络,侵删)

使用 ConnectivityManager (传统方法,API 26+ 推荐)

这是 Android 官方推荐的标准方法,特别是从 Android 8.0 (API 26) 开始,NetworkCapabilities 成为了获取网络信息的主要方式。

添加网络权限

AndroidManifest.xml 中必须声明网络访问权限。

<!-- 允许应用完全访问网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 从 Android 9 (API 28) 开始,如果应用使用 cleartext traffic (如 HTTP),需要显式声明 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

判断网络连接状态 (是否联网)

这个方法可以判断设备是否有任何可用的网络连接。

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
public class NetworkUtils {
    /**
     * 检查设备是否有任何可用的网络连接
     * @param context 上下文
     * @return true 有网络,false 无网络
     */
    public static boolean isNetworkAvailable(Context context) {
        if (context == null) {
            return false;
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            // 从 Android 10 (API 29) 开始,推荐使用 getDefaultNetwork()
            Network network = connectivityManager.getActiveNetwork();
            if (network != null) {
                NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
                if (capabilities != null) {
                    // 只要满足以下任意一种,就认为有网络连接
                    return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                           capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                           capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                           capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH);
                }
            }
        }
        return false;
    }
}

判断具体的网络类型

要判断是 Wi-Fi、移动数据还是其他类型,我们需要检查 NetworkCapabilities 中的 TRANSPORT 类型。

android 网络类型判断-图2
(图片来源网络,侵删)
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
public class NetworkUtils {
    // ... isNetworkAvailable 方法如上 ...
    /**
     * 获取当前网络类型
     * @param context 上下文
     * @return 网络类型字符串 (Wi-Fi, Mobile, Ethernet, None)
     */
    public static String getNetworkType(Context context) {
        if (context == null) {
            return "None";
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            Network network = connectivityManager.getActiveNetwork();
            if (network != null) {
                NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
                if (capabilities != null) {
                    if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                        return "Wi-Fi";
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                        return "Mobile";
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                        return "Ethernet";
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
                        return "Bluetooth";
                    }
                }
            }
        }
        return "None";
    }
}

监听网络状态变化

网络状态不是一成不变的,当 Wi-Fi 断开或切换到移动数据时,你的应用需要知道,可以通过 NetworkCallback 来实现。

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
public class NetworkMonitor {
    private ConnectivityManager.NetworkCallback networkCallback;
    private ConnectivityManager connectivityManager;
    public void register(Context context) {
        connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) return;
        NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build();
        networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                // 网络可用时调用
                // 可以在这里调用 NetworkUtils.getNetworkType() 获取类型
                String networkType = NetworkUtils.getNetworkType(context);
                // ... 你的逻辑 ...
            }
            @Override
            public void onLost(Network network) {
                // 网络丢失时调用
                // ... 你的逻辑 ...
            }
            @Override
            public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
                // 网络能力改变时调用(从 4G 切换到 5G)
                // ... 你的逻辑 ...
            }
        };
        // 注册回调
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(networkCallback);
        } else {
            // 对于 N 以下的版本,需要使用 registerNetworkCallback
            connectivityManager.registerNetworkCallback(request, networkCallback);
        }
    }
    public void unregister() {
        if (connectivityManager != null && networkCallback != null) {
            connectivityManager.unregisterNetworkCallback(networkCallback);
        }
    }
}

使用 NetworkMonitor

在你的 Activity 或 Service 的生命周期中管理它。

public class MyActivity extends AppCompatActivity {
    private NetworkMonitor networkMonitor;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        networkMonitor = new NetworkMonitor();
    }
    @Override
    protected void onResume() {
        super.onResume();
        networkMonitor.register(this);
    }
    @Override
    protected void onPause() {
        super.onPause();
        networkMonitor.unregister();
    }
}

使用 TelephonyManager (获取移动网络详细类型)

ConnectivityManager 可以告诉你当前是 "Mobile",但无法区分是 2G, 3G, 4G 还是 5G,要获取这些详细的移动网络信息,需要使用 TelephonyManager

android 网络类型判断-图3
(图片来源网络,侵删)

添加权限

TelephonyManager 是敏感 API,需要声明权限。

<!-- 获取网络状态信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 从 Android 10 (API 29) 开始,需要 READ_PHONE_STATE 来获取网络信息 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

获取详细网络类型

import android.annotation.SuppressLint;
import android.content.Context;
import android.telephony.TelephonyManager;
public class MobileNetworkUtils {
    @SuppressLint("MissingPermission") // 注意:实际开发中需要处理权限
    public static String getMobileNetworkType(Context context) {
        if (context == null) {
            return "Unknown";
        }
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager == null) {
            return "Unknown";
        }
        // 从 Android 9 (API 28) 开始,getNetworkType() 已弃用,推荐使用 getNetworkType()
        // 但新方法需要 READ_PHONE_STATE 权限
        int networkType = telephonyManager.getNetworkType();
        switch (networkType) {
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
                return "2G";
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return "3G";
            case TelephonyManager.NETWORK_TYPE_LTE:
                return "4G";
            case TelephonyManager.NETWORK_TYPE_NR:
                return "5G";
            default:
                return "Unknown";
        }
    }
}

注意权限问题:在 Android 6.0 (API 23) 及以上版本,READ_PHONE_STATE 是一个危险权限,必须在运行时动态请求,否则会抛出 SecurityException


总结与最佳实践

需求 推荐API 关键类/方法 说明
判断是否联网 ConnectivityManager getActiveNetwork(), getNetworkCapabilities() 官方标准方法,适用于所有 Android 版本。
判断网络大类 ConnectivityManager NetworkCapabilities.hasTransport() 可区分 Wi-Fi, Mobile, Ethernet 等。
判断移动网络子类 TelephonyManager getNetworkType() 可区分 2G, 3G, 4G, 5G,需要 READ_PHONE_STATE 权限。
监听网络变化 ConnectivityManager registerDefaultNetworkCallback() 实时响应网络状态变化,是现代 Android 应用的首选。

完整逻辑建议:

  1. 首选 ConnectivityManager:用它来判断是否有网络以及网络的大类别(Wi-Fi/Mobile)。
  2. 使用 TelephonyManager 增强信息:当确定当前是移动网络时,再调用 TelephonyManager 来获取更详细的 4G/5G 信息。
  3. 注册 NetworkCallback:在应用启动时注册一个全局的网络监听器,以便在后台也能及时响应网络变化。
  4. 处理权限:务必处理好 READ_PHONE_STATE 权限的申请和检查。
分享:
扫描分享到社交APP
上一篇
下一篇