Android | 网络类型判断工具类

欢迎关注我的公众号:CnPeng。

在 Android 中获取网络类型时,我们之前通常是先使用 ConnectivityManager.getActiveNetworkInfo() 判断是不是 Wifi , 然后通过 TelephonyManager.getNetworkType() 判断具体是 3G 还是 4G。

但是,这两个函数分别在 API23(Android M)和 API24(Android N)中已经被标记为 @Deprecated

那么,在更高版本的 Android 系统中,我们该如何判断 Wifi 和 具体的移动网络类型呢?

1.1 Android M 以上版本判断是不是 Wifi

先获取网络连接管理器 ConnectivityManager 对象,

ConnectivityManager connectManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);

然后获取当前活动的网络对象(Network)信息:

Network network = connectManager.getActiveNetwork();

再获取描述当前网络对象属性(能力)的 NetworkCapabilities 对象:

NetworkCapabilities capabilities = connectManager.getNetworkCapabilities(network);

通过 NetworkCapabilities.hasCapability() 中可以获取某个网络属性的状态,下面代码判断网络是否已经连接。需要注意,连接上并不代表能访问网络,比如连接到的无线路由器没有接入互联网:

/**
 * CnPeng:1/22/21 5:18 PM 是否已经连接到网络(连接上但不代表可以访问网络)
 */
private boolean isNetConnected(NetworkCapabilities capabilities) {
    boolean hasCapability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    Log.d(TAG, "是否已经连接到网络:" + hasCapability);
    return hasCapability;
}

当网络已经连接上了,那么我么再通过 NetworkCapabilities.hasTransport() 来判断当前连接网络类型:


/**
 * CnPeng:1/22/21 4:14 PM 判断是不是 Wifi
 */
private boolean isWifi(NetworkCapabilities capabilities) {
    boolean hasWifiTrans = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
    Log.d(TAG, "连接到 Wifi网络:" + hasWifiTrans + "| -------------------------");

    return hasWifiTrans;
}

1.2 Android N 以上版本判断移动网络类型

先获取 TelephonyManager 对象,该对象提供了电话机本身的一些服务信息:

TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);

然后通过 TelephonyManager.getDataNetworkType() 可以获取当前连接到的移动网络类型:

int netWorkType;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    netWorkType = telephonyManager.getDataNetworkType();
} 

获取到网络类型之后,我们通常还需要区分是 2G 、3G、4G ,其对应关系如下:

NetworkType类型说明
GPRS2G(2.5)General Packet Radia Service 114kbps
EDGE2G(2.75G)Enhanced Data Rate for GSM Evolution 384kbps
CDMA2G 电信Code Division Multiple Access 码分多址
1xRTT2G CDMA20001xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
IDEN2GIntegrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
UMTS3G WCDMA 联通3GUniversal Mobile Telecommunication System 完整的3G移动通信技术标准
EVDO_03G (EVDO 全称 CDMA2000 1xEV-DO)Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
EVDO_A3G1.8mbps - 3.1mbps 属于3G过渡,3.5G
EVDO_B3G EV-DORev.B 14.7Mbps 下行 3.5G
HSPA3G (分HSDPA,HSUPA)High Speed Packet Access
HSPAP3GHSPAP 比 HSDPA 快些
HSDPA3.5G高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
HSUPA3.5GHigh Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
EHRPD3GCDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
LTE4GLong Term Evolution FDD-LTETDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G

1.3 完整示例代码

  • CpNetUtil.java
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Log;

import androidx.annotation.RequiresPermission;

import java.util.List;

/**
 * CnPeng 1/22/21
 * 功用:网络工具类
 * 其他:
 */
class CpNetUtil {
    private static final CpNetUtil ourInstance = new CpNetUtil();
    private final        String    TAG         = getClass().getSimpleName();

    static CpNetUtil getInstance() {
        return ourInstance;
    }

    private CpNetUtil() {
    }


    /**
     * CnPeng:1/22/21 10:11 AM 官方文档参考:https://developer.android.google.cn/training/basics/network-ops/reading-network-state
     *
     * ConnectivityManager 管理器 | 系统连接状态:the state of connectivity in the system
     * Network             当前连接的网络对象  | ,网络切换后会变更为新的 Network 对象:one of the networks that the device is currently connected to
     *
     * LinkProperties      网络详细信息 | 如 DNS、IP 、interface name 、proxy
     * NetworkCapabilities 网络属性 | properties of a network, such as the transports (Wi-Fi, cellular, Bluetooth) and what the network is capable o
     */
    @SuppressLint("MissingPermission")
    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    public CpNetEnum getNetType(Context ctx) throws SecurityException {
        ConnectivityManager connectManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = connectManager.getActiveNetwork();

            NetworkCapabilities capabilities = connectManager.getNetworkCapabilities(network);

            if (null == capabilities || !isNetConnected(capabilities)) {
                return CpNetEnum.TYPE_NONE;
            }

            if (isWifi(capabilities)) {
                return CpNetEnum.TYPE_WIFI;
            }
        } else {
            NetworkInfo networkInfo = connectManager.getActiveNetworkInfo();
            if (null == networkInfo) {
                return CpNetEnum.TYPE_NONE;
            }
            if (ConnectivityManager.TYPE_WIFI == networkInfo.getType()) {
                return CpNetEnum.TYPE_WIFI;
            }
        }
        return getMobileNetType(ctx);
    }

    /**
     * CnPeng:1/22/21 4:28 PM 获取移动数据类型
     */
    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    private CpNetEnum getMobileNetType(Context ctx) throws SecurityException {
        TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);

        if (null == telephonyManager) {
            return CpNetEnum.TYPE_NONE;
        }

        int netWorkType;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            netWorkType = telephonyManager.getDataNetworkType();
        } else {
            netWorkType = telephonyManager.getNetworkType();
        }

        return convert2CusNetType(netWorkType);
    }

    /**
     * CnPeng:1/22/21 4:51 PM 将系统的网络 Type 转换成我们需要的标识
     *
     * GPRS : 2G(2.5) General Packet Radia Service 114kbps
     * EDGE : 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
     * CDMA : 2G 电信 Code Division Multiple Access 码分多址
     * 1xRTT : 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
     * IDEN : 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
     *
     * UMTS : 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
     * EVDO_0 : 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
     * EVDO_A : 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G
     * EVDO_B : 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
     * HSPA : 3G (分HSDPA,HSUPA) High Speed Packet Access
     * HSPAP : 3G HSPAP 比 HSDPA 快些
     * HSDPA : 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
     * HSUPA : 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
     * EHRPD : 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
     *
     * LTE : 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G
     */
    private CpNetEnum convert2CusNetType(int netWorkType) {
        switch (netWorkType) {

            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return CpNetEnum.TYPE_2G;

            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
                return CpNetEnum.TYPE_3G;

            case TelephonyManager.NETWORK_TYPE_LTE:
            case 19: // 19 对应的是 NETWORK_TYPE_LTE_CA,被标记为 hide 了,所以直接使用 19 判断
                return CpNetEnum.TYPE_4G;

            case TelephonyManager.NETWORK_TYPE_NR:
                return CpNetEnum.TYPE_5G;
            case TelephonyManager.NETWORK_TYPE_UNKNOWN:
            default:
                return CpNetEnum.TYPE_OTHER;
        }
    }

    /**
     * CnPeng:1/22/21 4:14 PM 判断是不是 Wifi
     */
    private boolean isWifi(NetworkCapabilities capabilities) {
        boolean hasWifiTrans = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
        Log.d(TAG, "连接到 Wifi网络:" + hasWifiTrans + "| -------------------------");

        return hasWifiTrans;
    }

    /**
     * CnPeng:1/25/21 8:38 AM 是不是蜂窝网络(即移动数据网络)
     * 注意:这个不准确,打开 Wifi 开关,但未连接到任意网络时,此处会返回 true
     */
    private boolean isCellular(NetworkCapabilities capabilities) {
        boolean isCellular = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
        Log.d(TAG, "连接到的是移动数据网络:" + isCellular);
        return isCellular;
    }

    /**
     * CnPeng:1/25/21 8:36 AM 是否可以进行网络访问
     */
    @TargetApi(23)
    private boolean isNetValidated(NetworkCapabilities capabilities) {
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
    }

    /**
     * CnPeng:1/22/21 5:18 PM 是否已经连接到网络(连接上但不代表可以访问网络)
     */
    private boolean isNetConnected(NetworkCapabilities capabilities) {
        boolean hasCapability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        Log.d(TAG, "是否已经连接到网络:" + hasCapability);
        return hasCapability;
    }

    /**
     * CnPeng:1/22/21 4:15 PM 获取 IP 地址等信息
     */
    private void getLinkProperties(ConnectivityManager connectManager, Network curNetObj) {
        LinkProperties linkProperties = connectManager.getLinkProperties(curNetObj);
        List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
        if (null != linkAddresses && !linkAddresses.isEmpty()) {
            // 包含 IPV4 和 IPV6 两种地址
            for (LinkAddress linkAddress : linkAddresses) {
                String hostAddress = linkAddress.getAddress().getHostAddress();
                Log.d(TAG, "主机地址:" + hostAddress);
            }
        }
    }
}
  • CpNetEnum.java
/**
 * CnPeng 1/22/21
 * 功用:自定义的网络类型
 * 其他:
 */
enum CpNetEnum {

    //CnPeng:1/22/21 4:26 PM  无网络
    TYPE_NONE(-1),
    //CnPeng:1/22/21 4:26 PM  其他网络类型
    TYPE_OTHER(0),
    TYPE_WIFI(1),
    TYPE_2G(2),
    TYPE_3G(3),
    TYPE_4G(4),
    TYPE_5G(5);

    private final int value;

    CpNetEnum(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}
  • MainActivity.java
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 666);
        } else {
            CpNetEnum netType = CpNetUtil.getInstance().getNetType(this);
            Log.d("MainActivity", netType.name());
        }

        // 不确定是否已经申请权限时,需要做如下 try catch.
        // try {
        //     GxtNetEnum netType = GxtNetUtil.getInstance().getNetType(this);
        //     Log.d("MainActivity", netType.name());
        // } catch (SecurityException e) {
        //     e.printStackTrace();
        // }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 666 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            @SuppressLint("MissingPermission")
            CpNetEnum netType = CpNetUtil.getInstance().getNetType(this);
            Log.d("MainActivity", netType.name());
        } else {
            Log.d("MainActivity", "权限被拒绝了");
        }
    }
}

在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CnPeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值