核心概念
- 网络类型:指连接的类型,如 Wi-Fi, 移动数据 (蜂窝网络)。
- 网络子类型:指在移动数据网络下的具体技术,如 2G (GPRS), 3G (UMTS/HSPA), 4G (LTE), 5G (NR)。
- 网络能力:一个更现代的概念,描述了网络连接能做什么(是否可以上网,是否是低延迟等)。
使用 TelephonyManager (传统方法,已弃用但仍可用)
这是最直接的方法,专门用于获取手机网络相关的信息。注意:从 Android 10 (API 29) 开始,在后台访问 TelephonyManager 需要申请 READ_PHONE_STATE 权限,并且很多方法被标记为 @Deprecated。

添加权限
在 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;
}
}
使用 ConnectivityManager 和 NetworkCapabilities (推荐,现代方法)
这是 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 |
实时监听网络变化,响应及时 | 实现相对复杂,需要管理生命周期 | 需要根据网络状态变化执行不同操作的应用(如视频清晰度切换) |
推荐的最终方案:

- 判断“是否是移动网络”:使用
ConnectivityManager和NetworkCapabilities的hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR),这是最可靠且权限友好的方式。 - 判断“移动网络的具体类型是否为 4G”:在确认是移动网络后,再调用
TelephonyManager.getNetworkType()并检查其返回值是否为NETWORK_TYPE_LTE。 - 处理权限:如果你的
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;
}
