睿诚科技协会

Android如何精准判断当前是否为4G网络?

核心概念

  1. 网络类型:指连接的类型,如 Wi-Fi, 移动数据 (蜂窝网络)。
  2. 网络子类型:指在移动数据网络下的具体技术,如 2G (GPRS), 3G (UMTS/HSPA), 4G (LTE), 5G (NR)。
  3. 网络能力:一个更现代的概念,描述了网络连接能做什么(是否可以上网,是否是低延迟等)。

使用 TelephonyManager (传统方法,已弃用但仍可用)

这是最直接的方法,专门用于获取手机网络相关的信息。注意:从 Android 10 (API 29) 开始,在后台访问 TelephonyManager 需要申请 READ_PHONE_STATE 权限,并且很多方法被标记为 @Deprecated

Android如何精准判断当前是否为4G网络?-图1
(图片来源网络,侵删)

添加权限

AndroidManifest.xml 中添加网络状态和电话状态的权限:

<!-- 网络状态权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 电话状态权限 (API 29+ 后台访问需要) -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

编写代码

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.TelephonyManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class NetworkUtils {
    /**
     * 检查当前网络是否是 4G (LTE)
     * @param context 上下文
     * @return true 如果是 4G 网络,否则 false
     */
    public static boolean is4GNetwork(Context context) {
        // 1. 首先检查是否有移动网络连接
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return false;
        }
        // 2. 获取活动网络信息 (旧 API 方法)
        // 注意:在 Android 10+ 中,getActiveNetworkInfo() 可能返回 null,推荐使用 NetworkCallback
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetworkInfo == null || !activeNetworkInfo.isConnectedOrConnecting()) {
            return false;
        }
        // 3. 检查是否是移动网络
        if (activeNetworkInfo.getType() != ConnectivityManager.TYPE_MOBILE) {
            return false;
        }
        // 4. 使用 TelephonyManager 获取具体网络类型
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager == null) {
            return false;
        }
        // 检查权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10+ 需要特殊权限,在后台应用中可能无法获取
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) 
                != PackageManager.PERMISSION_GRANTED) {
                // 如果没有权限,可以尝试通过 NetworkCapabilities 判断 (见方法二)
                // 或者直接返回 false,或者提示用户授予权限
                return false;
            }
        }
        int networkType = telephonyManager.getNetworkType();
        // 定义 4G (LTE) 的网络类型常量
        return networkType == TelephonyManager.NETWORK_TYPE_LTE;
    }
}

使用 ConnectivityManagerNetworkCapabilities (推荐,现代方法)

这是 Android 7.0 (API 24) 引入的更现代、更可靠的方法,它不直接依赖 TelephonyManager,因此权限要求更宽松(只需要 ACCESS_NETWORK_STATE),并且能更好地处理网络切换。

添加权限

<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.os.Build;
public class NetworkUtils {
    /**
     * 使用 NetworkCapabilities 检查当前网络是否是 4G (LTE)
     * 这是推荐的方法
     * @param context 上下文
     * @return true 如果是 4G 网络,否则 false
     */
    public static boolean is4GNetworkModern(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            // 如果系统版本低于 Android 6.0,回退到旧方法
            return is4GNetworkLegacy(context);
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return false;
        }
        // 获取当前活动的网络
        Network activeNetwork = connectivityManager.getActiveNetwork();
        if (activeNetwork == null) {
            return false;
        }
        // 获取网络能力
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
        if (capabilities == null) {
            return false;
        }
        // 检查:
        // 1. 网络是蜂窝网络 (TRANSPORT_CELLULAR)
        // 2. 网络已连接且可用 (NET_CAPABILITY_VALIDATED 和 NET_CAPABILITY_INTERNET)
        // 3. 网络下行的速度满足 4G 的典型特征 (NET_CAPABILITY_NOT_METERED 通常也满足)
        // 注意:NetworkCapabilities 不直接提供 LTE/4G 的判断标志,
        // 但它通过 TRANSPORT_CELLULAR 来确认是移动数据。
        // 要精确判断 4G,通常还是需要结合 TelephonyManager。
        // 这个方法更适合判断“是否是移动数据”,并配合其他方式判断 4G。
        // 更精确的判断方式是:确认是蜂窝网络,TelephonyManager 的网络类型是 LTE
        // 最佳实践是结合两种方法。
        return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
    }
    /**
     * 一个更精确的现代方法:结合 NetworkCapabilities 和 TelephonyManager
     */
    public static boolean is4GNetworkPrecise(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return is4GNetworkLegacy(context);
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return false;
        }
        Network activeNetwork = connectivityManager.getActiveNetwork();
        if (activeNetwork == null) {
            return false;
        }
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
        // 1. 先用 NetworkCapabilities 快速判断是否是移动网络
        if (capabilities == null || !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return false;
        }
        // 2. 再用 TelephonyManager 精确判断网络子类型是否为 LTE
        // 这样可以避免在 Wi-Fi 等非移动网络上进行不必要的 TelephonyManager 调用
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager == null) {
            return false;
        }
        // 权限检查同方法一
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // ... 权限检查代码 ...
        }
        int networkType = telephonyManager.getNetworkType();
        return networkType == TelephonyManager.NETWORK_TYPE_LTE;
    }
    /**
     * 旧版 API 的判断逻辑 (API < 23)
     */
    private static boolean is4GNetworkLegacy(Context context) {
        // ... 同方法一中的逻辑 ...
        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) return false;
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (activeNetwork == null || !activeNetwork.isConnectedOrConnecting()) {
            return false;
        }
        if (activeNetwork.getType() != ConnectivityManager.TYPE_MOBILE) {
            return false;
        }
        TelephonyManager tm = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null) return false;
        return tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE;
    }
}

使用 NetworkCallback (监听网络变化)

如果你需要在网络状态改变时(从 Wi-Fi 切换到 4G)得到实时通知,可以使用 NetworkCallback,这通常在 Application 类或 Service 中注册。

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Log;
public class NetworkMonitor {
    private static final String TAG = "NetworkMonitor";
    private Context context;
    private ConnectivityManager connectivityManager;
    public NetworkMonitor(Context context) {
        this.context = context.getApplicationContext();
        this.connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }
    public void startMonitoring() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // Android 7.0+ 使用 registerDefaultNetworkCallback
            connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    checkNetwork(network);
                }
                @Override
                public void onLost(Network network) {
                    // 网络连接丢失
                    Log.d(TAG, "Network lost");
                }
                @Override
                public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
                    // 网络能力改变时也会触发
                    checkNetwork(network);
                }
            });
        } else {
            // Android 6.0 及以下需要手动检查
            // ...
        }
    }
    private void checkNetwork(Network network) {
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
        if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            // 是移动网络,进一步判断是否为 4G
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (telephonyManager != null) {
                int networkType = telephonyManager.getNetworkType();
                if (networkType == TelephonyManager.NETWORK_TYPE_LTE) {
                    Log.d(TAG, "Current network is 4G (LTE)");
                    // 在这里执行你的 4G 网络逻辑
                } else {
                    Log.d(TAG, "Current network is Cellular but not 4G. Type: " + networkType);
                }
            }
        } else {
            Log.d(TAG, "Current network is not Cellular (e.g., Wi-Fi)");
        }
    }
    public void stopMonitoring() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.unregisterNetworkCallback(new ConnectivityManager.NetworkCallback());
        }
    }
}

总结与最佳实践

方法 优点 缺点 适用场景
TelephonyManager 直观,直接获取网络子类型 API 29+ 需要危险权限 READ_PHONE_STATE,后台受限,方法已弃用 旧项目兼容,或在新项目中作为辅助判断
ConnectivityManager + NetworkCapabilities 权限要求低,API 24+ 推荐方式,能更好处理网络变化 不直接提供 4G 判断,需结合 TelephonyManager 所有新项目首选,用于判断网络类型(移动/Wi-Fi)
NetworkCallback 实时监听网络变化,响应及时 实现相对复杂,需要管理生命周期 需要根据网络状态变化执行不同操作的应用(如视频清晰度切换)

推荐的最终方案:

Android如何精准判断当前是否为4G网络?-图2
(图片来源网络,侵删)
  1. 判断“是否是移动网络”:使用 ConnectivityManagerNetworkCapabilitieshasTransport(NetworkCapabilities.TRANSPORT_CELLULAR),这是最可靠且权限友好的方式。
  2. 判断“移动网络的具体类型是否为 4G”:在确认是移动网络后,再调用 TelephonyManager.getNetworkType() 并检查其返回值是否为 NETWORK_TYPE_LTE
  3. 处理权限:如果你的 targetSdkVersion 是 29 或更高,并且需要在后台或没有界面的地方访问 TelephonyManager,务必在 AndroidManifest.xml 中声明 READ_PHONE_STATE 权限,并在运行时请求它,如果只是在前台检查,很多情况下可以正常工作。

示例代码片段(最佳实践结合):

public boolean is4G(Context context) {
    // 1. 检查是否是移动网络 (现代方法)
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm == null) return false;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Network network = cm.getActiveNetwork();
        if (network == null) return false;
        NetworkCapabilities caps = cm.getNetworkCapabilities(network);
        if (caps == null || !caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return false; // 不是移动网络
        }
    } else {
        // 旧版 API 检查
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info == null || info.getType() != ConnectivityManager.TYPE_MOBILE) {
            return false; // 不是移动网络
        }
    }
    // 2. 检查是否是 LTE (传统方法)
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    if (tm == null) return false;
    // 权限检查 (根据你的 targetSdkVersion 决定是否需要运行时检查)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) 
            != PackageManager.PERMISSION_GRANTED) {
            // 没有权限,无法确定,可以返回 false 或提示用户
            return false; 
        }
    }
    return tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE;
}
Android如何精准判断当前是否为4G网络?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇