核心概念:网络类型判断的关键
无论使用哪种方法,核心都是获取到当前活动的 Network 对象,然后通过 NetworkCapabilities 来查询该网络的能力(Capabilities),其中就包括网络类型(传输类型)。

NetworkCapabilities.NET_TRANSPORT_CELLULAR: 表示这是一个蜂窝网络(移动数据,如 2G, 3G, 4G, 5G)。NetworkCapabilities.TRANSPORT_TYPE_LTE: 表示这是一个 LTE 网络(即我们常说的 4G)。注意:这个常量在 Android 9.0 (API 28) 才被引入。
使用 ConnectivityManager (推荐,现代方式)
这是从 Android 6.0 (API 23) 开始引入的、官方推荐的现代网络管理方式,它更准确、更安全,并且是处理所有网络相关操作的首选。
实现步骤:
- 获取
ConnectivityManager实例。 - 获取当前活动的网络,这需要
ACCESS_NETWORK_STATE权限。 - 获取该网络的
NetworkCapabilities。 - 检查
NetworkCapabilities是否同时满足两个条件:- 传输类型是
CELLULAR(蜂窝网络)。 - 具体子类型是
LTE(4G)。
- 传输类型是
代码示例 (Kotlin)
这是最简洁和推荐的写法。
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import androidx.core.app.ActivityCompat
/**
* 检查当前网络是否为4G (LTE)
* @param Context 上下文
* @return 如果是4G网络返回true,否则返回false
*/
fun is4GNetwork(context: Context): Boolean {
// 1. 获取ConnectivityManager
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
?: return false
// 2. 获取当前活动的网络
// 注意:从Android 10 (API 29)开始,getActiveNetwork()需要声明NETWORK_STACK权限,
// 对于普通应用,推荐使用getNetworks()来遍历所有网络,然后找到满足条件的网络。
// 但为了简化示例,这里使用getActiveNetwork(),并处理权限问题。
val activeNetwork = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.activeNetwork
} else {
// 对于旧版本,使用旧方法
@Suppress("DEPRECATION")
connectivityManager.activeNetworkInfo
} ?: return false // 如果没有活动网络,直接返回false
// 3. 获取NetworkCapabilities
val networkCapabilities = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.getNetworkCapabilities(activeNetwork)
} else {
// 旧版本没有NetworkCapabilities,无法精确判断,此方法不适用
return false
} ?: return false // 如果无法获取能力,返回false
// 4. 检查网络类型
// 网络必须是蜂窝网络,并且具体类型是LTE
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_TYPE_LTE)
}
Java 版本代码示例
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.Build;
import androidx.core.app.ActivityCompat;
public class NetworkUtils {
public static boolean is4GNetwork(Context context) {
// 1. 获取ConnectivityManager
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return false;
}
// 2. 获取当前活动的网络
Network activeNetwork;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activeNetwork = connectivityManager.getActiveNetwork();
if (activeNetwork == null) {
return false;
}
} else {
// 旧版本处理
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected()) {
return false;
}
// 注意:旧版API无法直接使用Network对象,此方法主要针对新版本
return false; // 简化处理,实际中需要更复杂的兼容逻辑
}
// 3. 获取NetworkCapabilities
NetworkCapabilities networkCapabilities = connectivityManager
.getNetworkCapabilities(activeNetwork);
if (networkCapabilities == null) {
return false;
}
// 4. 检查网络类型
// 网络必须是蜂窝网络,并且具体类型是LTE
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_TYPE_LTE);
}
}
使用 TelephonyManager (传统方式)
在 Android 9.0 之前,判断网络类型主要依赖 TelephonyManager,它可以直接获取到网络的具体制式(如 GPRS, EDGE, UMTS, LTE 等)。
注意事项:
- 权限要求: 需要危险权限
READ_PHONE_STATE,从 Android 6.0 开始,需要动态申请。 - API 版本限制:
getNetworkType()方法在 Android 9.0 (API 28) 时被标记为@Deprecated,因为它无法区分 Wi-Fi 和蜂窝网络的具体类型,在 Android 10 (API 29) 及以上,它只返回NETWORK_TYPE_UNKNOWN。此方法仅适用于 Android 9.0 以下的版本。
代码示例 (Kotlin)
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.telephony.TelephonyManager
import androidx.core.app.ActivityCompat
/**
* 使用TelephonyManager检查是否为4G网络
* 注意:此方法在Android 9.0 (API 28)及以上已废弃,仅适用于旧版本
* @param Context 上下文
* @return 如果是4G网络返回true,否则返回false
*/
fun is4GNetworkLegacy(context: Context): Boolean {
// 1. 检查权限
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED
) {
// 如果没有权限,无法判断
return false
}
// 2. 获取TelephonyManager
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
?: return false
// 3. 获取网络类型
val networkType = telephonyManager.networkType
// 4. 判断是否为LTE (4G)
// 注意:这些常量在TelephonyManager中定义
return networkType == TelephonyManager.NETWORK_TYPE_LTE ||
networkType == TelephonyManager.NETWORK_TYPE_LTE_CA // LTE Carrier Aggregation
}
完整集成示例 (在 Activity/Fragment 中使用)
下面展示如何在 Activity 中结合权限请求,使用推荐的方法来判断网络。

添加权限到 AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 如果使用TelephonyManager,还需要这个权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
Activity 代码 (Kotlin)
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
// 现代方式:注册权限请求回调
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
// 权限被授予,可以执行检查
checkAndShowNetworkStatus()
} else {
// 权限被拒绝
Toast.makeText(this, "需要网络状态权限才能判断", Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val checkButton: Button = findViewById(R.id.check_button)
checkButton.setOnClickListener {
// 检查权限
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_NETWORK_STATE
) == PackageManager.PERMISSION_GRANTED -> {
// 已有权限,直接检查
checkAndShowNetworkStatus()
}
shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_NETWORK_STATE) -> {
// 用户之前拒绝过,可以在这里解释为什么需要这个权限
Toast.makeText(this, "需要此权限来检查网络类型", Toast.LENGTH_LONG).show()
// 再次请求
requestPermissionLauncher.launch(Manifest.permission.ACCESS_NETWORK_STATE)
}
else -> {
// 首次请求
requestPermissionLauncher.launch(Manifest.permission.ACCESS_NETWORK_STATE)
}
}
}
}
private fun checkAndShowNetworkStatus() {
// 使用现代方法进行判断
if (is4GNetwork(this)) {
Toast.makeText(this, "当前网络是 4G (LTE)", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "当前网络不是 4G (LTE)", Toast.LENGTH_SHORT).show()
}
}
// 这里粘贴上面提供的 is4GNetwork() 函数
fun is4GNetwork(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
?: return false
val activeNetwork = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.activeNetwork
} else {
@Suppress("DEPRECATION")
connectivityManager.activeNetworkInfo
} ?: return false
val networkCapabilities = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.getNetworkCapabilities(activeNetwork)
} else {
return false
} ?: return false
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_TYPE_LTE)
}
}
总结与建议
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| ConnectivityManager | 官方推荐,现代,准确,能区分不同类型的网络(Wi-Fi, 蜂窝等),是未来趋势。 | 代码稍复杂,需要处理不同 API 版本的兼容性。 | 所有新项目,特别是需要兼容 Android 6.0 及以上版本的应用。 |
| TelephonyManager | 实现简单,直接获取网络制式。 | 已废弃,在 Android 9.0+ 上无效;需要 READ_PHONE_STATE 权限,用户可能敏感。 |
维护旧项目,且目标 API 低于 28。 |
最终建议:
- 对于任何新的开发,请优先使用
ConnectivityManager的方法。 - 如果你的应用需要兼容非常古老的 Android 版本(低于 6.0),你可能需要结合两种方法,并使用
Build.VERSION.SDK_INT进行判断。 - 务必处理好运行时权限的申请,特别是
READ_PHONE_STATE(如果使用旧方法)和ACCESS_NETWORK_STATE(虽然普通权限,但最佳实践是声明)。

